From 7f89ddce05f0a5c985d6333fbe70a992da4bd244 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 16 Aug 2012 12:12:46 -0400 Subject: [PATCH] Fix: complete error handling of babeltrace API Signed-off-by: Mathieu Desnoyers --- converter/babeltrace.c | 2 +- formats/ctf/callbacks.c | 8 +- formats/ctf/events.c | 129 +++++++++++++++++++---------- formats/ctf/iterator.c | 17 +++- include/babeltrace/context.h | 7 +- include/babeltrace/ctf/callbacks.h | 6 +- include/babeltrace/ctf/iterator.h | 2 +- lib/context.c | 17 +++- lib/iterator.c | 26 +++++- lib/registry.c | 6 ++ lib/trace-collection.c | 11 ++- lib/trace-handle.c | 15 ++++ 12 files changed, 186 insertions(+), 60 deletions(-) diff --git a/converter/babeltrace.c b/converter/babeltrace.c index fd6586a5..946a1568 100644 --- a/converter/babeltrace.c +++ b/converter/babeltrace.c @@ -401,7 +401,7 @@ int bt_context_add_traces_recursive(struct bt_context *ctx, const char *path, node->fts_accpath, format_str, packet_seek, NULL, NULL); if (trace_id < 0) { - fprintf(stderr, "[warning] [Context] opening trace \"%s\" from %s " + fprintf(stderr, "[warning] [Context] cannot open trace \"%s\" from %s " "for reading.\n", node->fts_accpath, path); /* Allow to skip erroneous traces. */ ret = 1; /* partial error */ diff --git a/formats/ctf/callbacks.c b/formats/ctf/callbacks.c index 05ddf499..0c221f9d 100644 --- a/formats/ctf/callbacks.c +++ b/formats/ctf/callbacks.c @@ -73,8 +73,12 @@ int bt_ctf_iter_add_callback(struct bt_ctf_iter *iter, int i, stream_id; gpointer *event_id_ptr; unsigned long event_id; - struct trace_collection *tc = iter->parent.ctx->tc; + struct trace_collection *tc; + if (!iter || !callback) + return -EINVAL; + + tc = iter->parent.ctx->tc; for (i = 0; i < tc->array->len; i++) { struct ctf_trace *tin; struct trace_descriptor *td_read; @@ -181,6 +185,8 @@ void process_callbacks(struct bt_ctf_iter *iter, enum bt_cb_ret ret; struct bt_ctf_event ctf_data; + assert(iter && stream); + ret = extract_ctf_stream_event(stream, &ctf_data); /* process all events callback first */ diff --git a/formats/ctf/events.c b/formats/ctf/events.c index 5d92b087..a9f5c22e 100644 --- a/formats/ctf/events.c +++ b/formats/ctf/events.c @@ -42,8 +42,12 @@ const struct definition *bt_ctf_get_top_level_scope(const struct bt_ctf_event *c enum bt_ctf_scope scope) { struct definition *tmp = NULL; - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; + if (!ctf_event) + return NULL; + + event = ctf_event->parent; switch (scope) { case BT_TRACE_PACKET_HEADER: if (!event->stream) @@ -91,28 +95,28 @@ const struct definition *bt_ctf_get_field(const struct bt_ctf_event *ctf_event, struct definition *def; char *field_underscore; - if (scope) { - def = lookup_definition(scope, field); - /* - * optionally a field can have an underscore prefix, try - * to lookup the field with this prefix if it failed - */ - if (!def) { - field_underscore = g_new(char, strlen(field) + 2); - field_underscore[0] = '_'; - strcpy(&field_underscore[1], field); - def = lookup_definition(scope, field_underscore); - g_free(field_underscore); - } - if (bt_ctf_field_type(def) == CTF_TYPE_VARIANT) { - struct definition_variant *variant_definition; - variant_definition = container_of(def, - struct definition_variant, p); - return variant_definition->current_field; - } - return def; + if (!ctf_event || !scope || !field) + return NULL; + + def = lookup_definition(scope, field); + /* + * optionally a field can have an underscore prefix, try + * to lookup the field with this prefix if it failed + */ + if (!def) { + field_underscore = g_new(char, strlen(field) + 2); + field_underscore[0] = '_'; + strcpy(&field_underscore[1], field); + def = lookup_definition(scope, field_underscore); + g_free(field_underscore); } - return NULL; + if (bt_ctf_field_type(def) == CTF_TYPE_VARIANT) { + struct definition_variant *variant_definition; + variant_definition = container_of(def, + struct definition_variant, p); + return variant_definition->current_field; + } + return def; } const struct definition *bt_ctf_get_index(const struct bt_ctf_event *ctf_event, @@ -121,6 +125,9 @@ const struct definition *bt_ctf_get_index(const struct bt_ctf_event *ctf_event, { struct definition *ret = NULL; + if (!ctf_event || !field) + return NULL; + if (bt_ctf_field_type(field) == CTF_TYPE_ARRAY) { struct definition_array *array_definition; array_definition = container_of(field, @@ -139,10 +146,12 @@ const char *bt_ctf_event_name(const struct bt_ctf_event *ctf_event) { struct ctf_event_declaration *event_class; struct ctf_stream_declaration *stream_class; - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; - if (!event) + if (!ctf_event) return NULL; + + event = ctf_event->parent; stream_class = event->stream->stream_class; event_class = g_ptr_array_index(stream_class->events_by_id, event->stream->event_id); @@ -151,16 +160,18 @@ const char *bt_ctf_event_name(const struct bt_ctf_event *ctf_event) const char *bt_ctf_field_name(const struct definition *def) { - if (def) - return rem_(g_quark_to_string(def->name)); - return NULL; + if (!def) + return NULL; + + return rem_(g_quark_to_string(def->name)); } enum ctf_type_id bt_ctf_field_type(const struct definition *def) { - if (def) - return def->declaration->id; - return CTF_TYPE_UNKNOWN; + if (!def) + return CTF_TYPE_UNKNOWN; + + return def->declaration->id; } int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, @@ -168,6 +179,9 @@ int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, struct definition const * const **list, unsigned int *count) { + if (!ctf_event || !scope || !list || !count) + return -EINVAL; + switch (bt_ctf_field_type(scope)) { case CTF_TYPE_INTEGER: case CTF_TYPE_FLOAT: @@ -188,6 +202,7 @@ int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, } else { goto error; } + break; } case CTF_TYPE_UNTAGGED_VARIANT: goto error; @@ -205,6 +220,7 @@ int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, } else { goto error; } + break; } case CTF_TYPE_ARRAY: { @@ -220,6 +236,7 @@ int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, } else { goto error; } + break; } case CTF_TYPE_SEQUENCE: { @@ -235,6 +252,7 @@ int bt_ctf_get_field_list(const struct bt_ctf_event *ctf_event, } else { goto error; } + break; } default: break; @@ -254,8 +272,12 @@ struct bt_context *bt_ctf_event_get_context(const struct bt_ctf_event *ctf_event struct bt_context *ret = NULL; struct ctf_file_stream *cfs; struct ctf_trace *trace; - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; + if (!ctf_event) + return NULL; + + event = ctf_event->parent; cfs = container_of(event->stream, struct ctf_file_stream, parent); trace = cfs->parent.stream_class->trace; @@ -270,8 +292,12 @@ int bt_ctf_event_get_handle_id(const struct bt_ctf_event *ctf_event) int ret = -1; struct ctf_file_stream *cfs; struct ctf_trace *trace; - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; + + if (!ctf_event) + return -EINVAL; + event = ctf_event->parent; cfs = container_of(event->stream, struct ctf_file_stream, parent); trace = cfs->parent.stream_class->trace; @@ -283,7 +309,12 @@ int bt_ctf_event_get_handle_id(const struct bt_ctf_event *ctf_event) uint64_t bt_ctf_get_timestamp(const struct bt_ctf_event *ctf_event) { - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; + + if (!ctf_event) + return -1ULL; + + event = ctf_event->parent; if (event && event->stream->has_timestamp) return event->stream->real_timestamp; else @@ -292,7 +323,12 @@ uint64_t bt_ctf_get_timestamp(const struct bt_ctf_event *ctf_event) uint64_t bt_ctf_get_cycles(const struct bt_ctf_event *ctf_event) { - struct ctf_event_definition *event = ctf_event->parent; + struct ctf_event_definition *event; + + if (!ctf_event) + return -1ULL; + + event = ctf_event->parent; if (event && event->stream->has_timestamp) return event->stream->cycles_timestamp; else @@ -320,7 +356,7 @@ int bt_ctf_get_int_signedness(const struct definition *field) if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) { ret = get_int_signedness(field); } else { - ret = -1; + ret = -EINVAL; bt_ctf_field_set_error(-EINVAL); } @@ -334,7 +370,7 @@ int bt_ctf_get_int_base(const struct definition *field) if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) { ret = get_int_base(field); } else { - ret = -1; + ret = -EINVAL; bt_ctf_field_set_error(-EINVAL); } @@ -348,7 +384,7 @@ int bt_ctf_get_int_byte_order(const struct definition *field) if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) { ret = get_int_byte_order(field); } else { - ret = -1; + ret = -EINVAL; bt_ctf_field_set_error(-EINVAL); } @@ -362,7 +398,7 @@ ssize_t bt_ctf_get_int_len(const struct definition *field) if (field && bt_ctf_field_type(field) == CTF_TYPE_INTEGER) { ret = (ssize_t) get_int_len(field); } else { - ret = -1; + ret = -EINVAL; bt_ctf_field_set_error(-EINVAL); } @@ -374,7 +410,7 @@ enum ctf_string_encoding bt_ctf_get_encoding(const struct definition *field) enum ctf_string_encoding ret = 0; if (!field) - goto end; + goto error; if (bt_ctf_field_type(field) == CTF_TYPE_INTEGER) ret = get_int_encoding(field); @@ -382,8 +418,6 @@ enum ctf_string_encoding bt_ctf_get_encoding(const struct definition *field) ret = get_string_encoding(field); else goto error; - -end: return ret; error: @@ -462,7 +496,7 @@ int bt_ctf_get_event_decl_list(int handle_id, struct bt_context *ctx, struct trace_descriptor *td; struct ctf_trace *tin; - if (!ctx) + if (!ctx || !list || !count) goto error; handle = g_hash_table_lookup(ctx->trace_handles, @@ -485,6 +519,7 @@ const char *bt_ctf_get_decl_event_name(const struct bt_ctf_event_decl *event) { if (!event) return NULL; + return g_quark_to_string(event->parent.name); } @@ -500,6 +535,9 @@ int bt_ctf_get_decl_fields(struct bt_ctf_event_decl *event_decl, int ret = 0; *count = 0; + if (!event_decl || !list || !count) + return -EINVAL; + switch (scope) { case BT_EVENT_CONTEXT: if (event_decl->context_decl) { @@ -603,7 +641,8 @@ end: const char *bt_ctf_get_decl_field_name(const struct bt_ctf_field_decl *field) { - if (field) - return rem_(g_quark_to_string(((struct declaration_field *) field)->name)); - return NULL; + if (!field) + return NULL; + + return rem_(g_quark_to_string(((struct declaration_field *) field)->name)); } diff --git a/formats/ctf/iterator.c b/formats/ctf/iterator.c index f7b25f15..ec74e590 100644 --- a/formats/ctf/iterator.c +++ b/formats/ctf/iterator.c @@ -38,6 +38,9 @@ struct bt_ctf_iter *bt_ctf_iter_create(struct bt_context *ctx, struct bt_ctf_iter *iter; int ret; + if (!ctx) + return NULL; + iter = g_new0(struct bt_ctf_iter, 1); ret = bt_iter_init(&iter->parent, ctx, begin_pos, end_pos); if (ret) { @@ -57,6 +60,8 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter) struct bt_callback_chain *bt_chain; int i, j; + assert(iter); + /* free all events callbacks */ if (iter->main_callbacks.callback) g_array_free(iter->main_callbacks.callback, TRUE); @@ -83,15 +88,25 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter) struct bt_iter *bt_ctf_get_iter(struct bt_ctf_iter *iter) { + if (!iter) + return NULL; + return &iter->parent; } struct bt_ctf_event *bt_ctf_iter_read_event(struct bt_ctf_iter *iter) { struct ctf_file_stream *file_stream; - struct bt_ctf_event *ret = &iter->current_ctf_event; + struct bt_ctf_event *ret; struct ctf_stream_definition *stream; + /* + * We do not want to fail for any other reason than end of + * trace, hence the assert. + */ + assert(iter); + + ret = &iter->current_ctf_event; file_stream = heap_maximum(iter->parent.stream_heap); if (!file_stream) { /* end of file for all streams */ diff --git a/include/babeltrace/context.h b/include/babeltrace/context.h index 4a85ff99..ee2a724a 100644 --- a/include/babeltrace/context.h +++ b/include/babeltrace/context.h @@ -60,7 +60,7 @@ struct bt_context *bt_context_create(void); * * stream_list is a linked list of streams, it is used to open a trace where * the trace data is located in memory mapped areas instead of trace files, - * this argument should be set to NULL when path is not NULL. + * this argument should be set to NULL when path is NULL. * * The metadata parameter acts as a metadata override when not NULL, otherwise * the format handles the metadata opening. @@ -78,9 +78,10 @@ int bt_context_add_trace(struct bt_context *ctx, const char *path, /* * bt_context_remove_trace: Remove a trace from the context. * - * Effectively closing the trace. + * Effectively closing the trace. Return negative error value if trace + * is not in context. */ -void bt_context_remove_trace(struct bt_context *ctx, int trace_id); +int bt_context_remove_trace(struct bt_context *ctx, int trace_id); /* * bt_context_get and bt_context_put : increments and decrement the diff --git a/include/babeltrace/ctf/callbacks.h b/include/babeltrace/ctf/callbacks.h index 328762ca..597d4b17 100644 --- a/include/babeltrace/ctf/callbacks.h +++ b/include/babeltrace/ctf/callbacks.h @@ -58,13 +58,13 @@ void babeltrace_dependencies_destroy(struct bt_dependencies *dep); * * @callback: function pointer to call * @depends: struct bt_dependency detailing the required computation results. - * Ends with 0. + * Ends with 0. NULL is accepted as empty dependency. * @weak_depends: struct bt_dependency detailing the optional computation * results that can be optionally consumed by this - * callback. + * callback. NULL is accepted as empty dependency. * @provides: struct bt_dependency detailing the computation results * provided by this callback. - * Ends with 0. + * Ends with 0. NULL is accepted as empty dependency. * * "depends", "weak_depends" and "provides" memory is handled by the * babeltrace library after this call succeeds or fails. These objects diff --git a/include/babeltrace/ctf/iterator.h b/include/babeltrace/ctf/iterator.h index 1071def8..fe70b5e7 100644 --- a/include/babeltrace/ctf/iterator.h +++ b/include/babeltrace/ctf/iterator.h @@ -64,7 +64,7 @@ void bt_ctf_iter_destroy(struct bt_ctf_iter *iter); /* * bt_ctf_iter_read_event: Read the iterator's current event data. * - * @iter: trace collection iterator (input) + * @iter: trace collection iterator (input). Should NOT be NULL. * * Return current event on success, NULL on end of trace. */ diff --git a/lib/context.c b/lib/context.c index e2c1739c..dca4cb2b 100644 --- a/lib/context.c +++ b/lib/context.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include /* For O_RDONLY */ @@ -69,6 +70,9 @@ int bt_context_add_trace(struct bt_context *ctx, const char *path, struct bt_trace_handle *handle; int ret; + if (!ctx || !format_name || (!path && !stream_list)) + return -EINVAL; + fmt = bt_lookup_format(g_quark_from_string(format_name)); if (!fmt) { fprintf(stderr, "[error] [Context] Format \"%s\" unknown.\n\n", @@ -136,13 +140,17 @@ end: return ret; } -void bt_context_remove_trace(struct bt_context *ctx, int handle_id) +int bt_context_remove_trace(struct bt_context *ctx, int handle_id) { struct bt_trace_handle *handle; + if (!ctx) + return -EINVAL; + handle = g_hash_table_lookup(ctx->trace_handles, (gpointer) (unsigned long) handle_id); - assert(handle != NULL); + if (!handle) + return -ENOENT; /* Remove from containers */ trace_collection_remove(ctx->tc, handle->td); @@ -152,12 +160,13 @@ void bt_context_remove_trace(struct bt_context *ctx, int handle_id) /* Remove and free the handle */ g_hash_table_remove(ctx->trace_handles, (gpointer) (unsigned long) handle_id); - + return 0; } static void bt_context_destroy(struct bt_context *ctx) { + assert(ctx); finalize_trace_collection(ctx->tc); /* Remote all traces. The g_hash_table_destroy will call @@ -173,11 +182,13 @@ void bt_context_destroy(struct bt_context *ctx) void bt_context_get(struct bt_context *ctx) { + assert(ctx); ctx->refcount++; } void bt_context_put(struct bt_context *ctx) { + assert(ctx); ctx->refcount--; if (ctx->refcount == 0) bt_context_destroy(ctx); diff --git a/lib/iterator.c b/lib/iterator.c index 0d101048..f5f413e2 100644 --- a/lib/iterator.c +++ b/lib/iterator.c @@ -192,6 +192,9 @@ int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos) struct trace_collection *tc; int i, ret; + if (!iter || !iter_pos) + return -EINVAL; + switch (iter_pos->type) { case BT_SEEK_RESTORE: if (!iter_pos->u.restore) @@ -349,11 +352,15 @@ error_heap_init: struct bt_iter_pos *bt_iter_get_pos(struct bt_iter *iter) { struct bt_iter_pos *pos; - struct trace_collection *tc = iter->ctx->tc; + struct trace_collection *tc; struct ctf_file_stream *file_stream = NULL, *removed; struct ptr_heap iter_heap_copy; int ret; + if (!iter) + return NULL; + + tc = iter->ctx->tc; pos = g_new0(struct bt_iter_pos, 1); pos->type = BT_SEEK_RESTORE; pos->u.restore = g_new0(struct bt_saved_pos, 1); @@ -412,6 +419,9 @@ struct bt_iter_pos *bt_iter_create_time_pos(struct bt_iter *iter, { struct bt_iter_pos *pos; + if (!iter) + return NULL; + pos = g_new0(struct bt_iter_pos, 1); pos->type = BT_SEEK_TIME; pos->u.seek_time = timestamp; @@ -429,6 +439,9 @@ static int babeltrace_filestream_seek(struct ctf_file_stream *file_stream, { int ret = 0; + if (!file_stream || !begin_pos) + return -EINVAL; + switch (begin_pos->type) { case BT_SEEK_CUR: /* @@ -459,6 +472,9 @@ int bt_iter_init(struct bt_iter *iter, int i, stream_id; int ret = 0; + if (!iter || !ctx) + return -EINVAL; + if (ctx->current_iterator) { ret = -1; goto error_ctx; @@ -544,6 +560,9 @@ struct bt_iter *bt_iter_create(struct bt_context *ctx, struct bt_iter *iter; int ret; + if (!ctx) + return NULL; + iter = g_new0(struct bt_iter, 1); ret = bt_iter_init(iter, ctx, begin_pos, end_pos); if (ret) { @@ -555,6 +574,7 @@ struct bt_iter *bt_iter_create(struct bt_context *ctx, void bt_iter_fini(struct bt_iter *iter) { + assert(iter); if (iter->stream_heap) { heap_free(iter->stream_heap); g_free(iter->stream_heap); @@ -565,6 +585,7 @@ void bt_iter_fini(struct bt_iter *iter) void bt_iter_destroy(struct bt_iter *iter) { + assert(iter); bt_iter_fini(iter); g_free(iter); } @@ -574,6 +595,9 @@ int bt_iter_next(struct bt_iter *iter) struct ctf_file_stream *file_stream, *removed; int ret; + if (!iter) + return -EINVAL; + file_stream = heap_maximum(iter->stream_heap); if (!file_stream) { /* end of file for all streams */ diff --git a/lib/registry.c b/lib/registry.c index 829ede9d..3cef63d9 100644 --- a/lib/registry.c +++ b/lib/registry.c @@ -44,6 +44,7 @@ struct format *bt_lookup_format(bt_intern_str name) { if (!init_done) return NULL; + return g_hash_table_lookup(format_registry, (gconstpointer) (unsigned long) name); } @@ -61,6 +62,8 @@ void bt_fprintf_format_list(FILE *fp) { struct walk_data data; + assert(fp); + data.fp = fp; data.iter = 0; @@ -75,6 +78,9 @@ void bt_fprintf_format_list(FILE *fp) int bt_register_format(struct format *format) { + if (!format) + return -EINVAL; + if (!init_done) format_init(); diff --git a/lib/trace-collection.c b/lib/trace-collection.c index c1178748..9bc5b1fc 100644 --- a/lib/trace-collection.c +++ b/lib/trace-collection.c @@ -138,8 +138,12 @@ static void clock_add(gpointer key, gpointer value, gpointer user_data) int trace_collection_add(struct trace_collection *tc, struct trace_descriptor *td) { - struct ctf_trace *trace = container_of(td, struct ctf_trace, parent); + struct ctf_trace *trace; + if (!tc || !td) + return -EINVAL; + + trace = container_of(td, struct ctf_trace, parent); g_ptr_array_add(tc->array, td); trace->collection = tc; @@ -187,6 +191,9 @@ error: int trace_collection_remove(struct trace_collection *tc, struct trace_descriptor *td) { + if (!tc || !td) + return -EINVAL; + if (g_ptr_array_remove(tc->array, td)) { return 0; } else { @@ -197,6 +204,7 @@ int trace_collection_remove(struct trace_collection *tc, void init_trace_collection(struct trace_collection *tc) { + assert(tc); tc->array = g_ptr_array_new(); tc->clocks = g_hash_table_new(g_direct_hash, g_direct_equal); tc->single_clock_offset_avg = 0; @@ -211,6 +219,7 @@ void init_trace_collection(struct trace_collection *tc) */ void finalize_trace_collection(struct trace_collection *tc) { + assert(tc); g_ptr_array_free(tc->array, TRUE); g_hash_table_destroy(tc->clocks); } diff --git a/lib/trace-handle.c b/lib/trace-handle.c index 5058d373..f981adda 100644 --- a/lib/trace-handle.c +++ b/lib/trace-handle.c @@ -31,6 +31,9 @@ struct bt_trace_handle *bt_trace_handle_create(struct bt_context *ctx) { struct bt_trace_handle *th; + if (!ctx) + return NULL; + th = g_new0(struct bt_trace_handle, 1); th->id = ctx->last_trace_handle_id++; return th; @@ -43,6 +46,9 @@ void bt_trace_handle_destroy(struct bt_trace_handle *th) int bt_trace_handle_get_id(struct bt_trace_handle *th) { + if (!th) + return -1; + return th->id; } @@ -50,6 +56,9 @@ const char *bt_trace_handle_get_path(struct bt_context *ctx, int handle_id) { struct bt_trace_handle *handle; + if (!ctx) + return NULL; + handle = g_hash_table_lookup(ctx->trace_handles, (gpointer) (unsigned long) handle_id); if (!handle) @@ -63,6 +72,9 @@ uint64_t bt_trace_handle_get_timestamp_begin(struct bt_context *ctx, struct bt_trace_handle *handle; uint64_t ret; + if (!ctx) + return -1ULL; + handle = g_hash_table_lookup(ctx->trace_handles, (gpointer) (unsigned long) handle_id); if (!handle) { @@ -87,6 +99,9 @@ uint64_t bt_trace_handle_get_timestamp_end(struct bt_context *ctx, struct bt_trace_handle *handle; uint64_t ret; + if (!ctx) + return -1ULL; + handle = g_hash_table_lookup(ctx->trace_handles, (gpointer) (unsigned long) handle_id); if (!handle) { -- 2.34.1