X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-abi.c;h=f26ab5c42907f6a71aab27620e7ecbea10465e07;hb=ff0f57289ff0e6be25424081fabbbfc0e3b1b565;hp=acf3c849f2d7a9c69d0d9157638d594cd406d6b3;hpb=13b21cd60df2abab292653cead980ef27dbfab08;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index acf3c849..f26ab5c4 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -71,6 +71,7 @@ struct lttng_ust_obj { void *private_data; const struct lttng_ust_objd_ops *ops; int f_count; + int owner_ref; /* has ref from owner */ void *owner; char name[OBJ_NAME_LEN]; } s; @@ -126,6 +127,7 @@ end: obj->u.s.ops = ops; obj->u.s.f_count = 2; /* count == 1 : object is allocated */ /* count == 2 : allocated + hold ref */ + obj->u.s.owner_ref = 1; /* One owner reference */ obj->u.s.owner = owner; strncpy(obj->u.s.name, name, OBJ_NAME_LEN); obj->u.s.name[OBJ_NAME_LEN - 1] = '\0'; @@ -186,7 +188,7 @@ void objd_ref(int id) obj->u.s.f_count++; } -int lttng_ust_objd_unref(int id) +int lttng_ust_objd_unref(int id, int is_owner) { struct lttng_ust_obj *obj = _objd_get(id); @@ -196,6 +198,13 @@ int lttng_ust_objd_unref(int id) ERR("Reference counting error\n"); return -EINVAL; } + if (is_owner) { + if (!obj->u.s.owner_ref) { + ERR("Error decrementing owner reference"); + return -EINVAL; + } + obj->u.s.owner_ref--; + } if ((--obj->u.s.f_count) == 1) { const struct lttng_ust_objd_ops *ops = objd_ops(id); @@ -211,8 +220,16 @@ void objd_table_destroy(void) { int i; - for (i = 0; i < objd_table.allocated_len; i++) - (void) lttng_ust_objd_unref(i); + for (i = 0; i < objd_table.allocated_len; i++) { + struct lttng_ust_obj *obj; + + obj = _objd_get(i); + if (!obj) + continue; + if (!obj->u.s.owner_ref) + continue; /* only unref owner ref. */ + (void) lttng_ust_objd_unref(i, 1); + } free(objd_table.array); objd_table.array = NULL; objd_table.len = 0; @@ -241,8 +258,10 @@ void lttng_ust_objd_table_owner_cleanup(void *owner) continue; if (!obj->u.s.owner) continue; /* skip root handles */ + if (!obj->u.s.owner_ref) + continue; /* only unref owner ref. */ if (obj->u.s.owner == owner) - (void) lttng_ust_objd_unref(i); + (void) lttng_ust_objd_unref(i, 1); } } @@ -384,11 +403,13 @@ int lttng_abi_map_channel(int session_objd, struct channel *chan; struct lttng_ust_lib_ring_buffer_config *config; void *chan_data; + int wakeup_fd; uint64_t len; int ret; enum lttng_ust_chan_type type; chan_data = uargs->channel.chan_data; + wakeup_fd = uargs->channel.wakeup_fd; len = ust_chan->len; type = ust_chan->type; @@ -396,7 +417,8 @@ int lttng_abi_map_channel(int session_objd, case LTTNG_UST_CHAN_PER_CPU: break; default: - return -EINVAL; + ret = -EINVAL; + goto invalid; } if (session->been_active) { @@ -404,7 +426,7 @@ int lttng_abi_map_channel(int session_objd, goto active; /* Refuse to add channel to active session */ } - channel_handle = channel_handle_create(chan_data, len); + channel_handle = channel_handle_create(chan_data, len, wakeup_fd); if (!channel_handle) { ret = -EINVAL; goto handle_error; @@ -412,6 +434,7 @@ int lttng_abi_map_channel(int session_objd, chan = shmp(channel_handle, channel_handle->chan); assert(chan); + chan->handle = channel_handle; config = &chan->backend.config; lttng_chan = channel_get_private(chan); if (!lttng_chan) { @@ -453,6 +476,7 @@ int lttng_abi_map_channel(int session_objd, /* Initialize our lttng chan */ lttng_chan->chan = chan; + lttng_chan->tstate = 1; lttng_chan->enabled = 1; lttng_chan->ctx = NULL; lttng_chan->session = session; @@ -475,13 +499,30 @@ int lttng_abi_map_channel(int session_objd, objd_ref(session_objd); return chan_objd; + /* error path after channel was created */ objd_error: notransport: free(lttng_chan); alloc_error: channel_destroy(chan, channel_handle, 0); + return ret; + + /* + * error path before channel creation (owning chan_data and + * wakeup_fd). + */ handle_error: active: +invalid: + { + int close_ret; + + close_ret = close(wakeup_fd); + if (close_ret) { + PERROR("close"); + } + } + free(chan_data); return ret; } @@ -606,7 +647,7 @@ alloc_error: { int err; - err = lttng_ust_objd_unref(list_objd); + err = lttng_ust_objd_unref(list_objd, 1); assert(!err); } objd_error: @@ -686,7 +727,7 @@ alloc_error: { int err; - err = lttng_ust_objd_unref(list_objd); + err = lttng_ust_objd_unref(list_objd, 1); assert(!err); } objd_error: @@ -765,7 +806,7 @@ event_error: { int err; - err = lttng_ust_objd_unref(event_objd); + err = lttng_ust_objd_unref(event_objd, 1); assert(!err); } objd_error: @@ -853,7 +894,7 @@ int lttng_channel_release(int objd) struct lttng_channel *channel = objd_private(objd); if (channel) - return lttng_ust_objd_unref(channel->session->objd); + return lttng_ust_objd_unref(channel->session->objd, 0); return 0; } @@ -917,7 +958,7 @@ int lttng_enabler_release(int objd) struct lttng_enabler *enabler = objd_private(objd); if (enabler) - return lttng_ust_objd_unref(enabler->chan->objd); + return lttng_ust_objd_unref(enabler->chan->objd, 0); return 0; }