From: Mathieu Desnoyers Date: Tue, 13 Sep 2016 20:17:40 +0000 (-0400) Subject: Introduce file descriptor tracker X-Git-Tag: v2.9.0-rc1~5 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=6548fca464f68be5ded73be6b9a479daf08e62d6;p=lttng-ust.git Introduce file descriptor tracker Introduce a tracker for file descriptors used by lttng-ust. It exposes a new API in an internal header lttng_ust_safe_close_fd(), which is meant to be used by a LD_PRELOADed library overriding close() and closefrom() (BSD). This takes care of bugs caused by applications doing bulk close() or closefrom() of file descriptors soon after forking. We need to hold the ust_lock() to protect the fd tracker lock against fork. Since the fd tracker is needed across connect() (which allocates a file descriptor), we need to hold the ust_lock across connect(). Fixes: #253 Fixes: #626 Suggested-by: Aravind HT Signed-off-by: Mathieu Desnoyers --- diff --git a/include/Makefile.am b/include/Makefile.am index 47c715b1..277e4e69 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -33,6 +33,7 @@ noinst_HEADERS = \ usterr-signal-safe.h \ ust_snprintf.h \ ust-comm.h \ + ust-fd.h \ lttng/ust-tid.h \ lttng/bitfield.h \ lttng/ust-dlfcn.h \ diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 61acf754..0b2291b3 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -733,6 +733,7 @@ struct lttng_enum *lttng_ust_enum_get(struct lttng_session *session, const char *enum_name); void lttng_ust_dl_update(void *ip); +void lttng_ust_fixup_fd_tracker_tls(void); /* For backward compatibility. Leave those exported symbols in place. */ extern struct lttng_ctx *lttng_static_ctx; diff --git a/include/ust-fd.h b/include/ust-fd.h new file mode 100644 index 00000000..7cbcf47c --- /dev/null +++ b/include/ust-fd.h @@ -0,0 +1,36 @@ +#ifndef _LTTNG_UST_FD_H +#define _LTTNG_UST_FD_H + +/* + * Copyright (C) 2016 - Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This header is meant for liblttng and libust internal use ONLY. + * These declarations should NOT be considered stable API. + */ + +void lttng_ust_init_fd_tracker(void); +void lttng_ust_add_fd_to_tracker(int fd); +void lttng_ust_delete_fd_from_tracker(int fd); +void lttng_ust_lock_fd_tracker(void); +void lttng_ust_unlock_fd_tracker(void); + +int lttng_ust_safe_close_fd(int fd, int (*close_cb)(int)); +int lttng_ust_safe_closefrom_fd(int lowfd, int (*close_cb)(int)); + +#endif /* _LTTNG_UST_FD_H */ diff --git a/liblttng-ust-comm/Makefile.am b/liblttng-ust-comm/Makefile.am index 065dbbf7..b9043065 100644 --- a/liblttng-ust-comm/Makefile.am +++ b/liblttng-ust-comm/Makefile.am @@ -2,4 +2,4 @@ AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include noinst_LTLIBRARIES = liblttng-ust-comm.la -liblttng_ust_comm_la_SOURCES = lttng-ust-comm.c +liblttng_ust_comm_la_SOURCES = lttng-ust-comm.c lttng-ust-fd-tracker.c diff --git a/liblttng-ust-comm/lttng-ust-comm.c b/liblttng-ust-comm/lttng-ust-comm.c index c01eb9de..9fe6d288 100644 --- a/liblttng-ust-comm/lttng-ust-comm.c +++ b/liblttng-ust-comm/lttng-ust-comm.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -94,6 +95,8 @@ const char *lttng_ust_strerror(int code) * ustcomm_connect_unix_sock * * Connect to unix socket using the path name. + * + * Caller handles FD tracker. */ int ustcomm_connect_unix_sock(const char *pathname, long timeout) { @@ -257,16 +260,22 @@ int ustcomm_listen_unix_sock(int sock) * ustcomm_close_unix_sock * * Shutdown cleanly a unix socket. + * + * Handles fd tracker internally. */ int ustcomm_close_unix_sock(int sock) { int ret; + lttng_ust_lock_fd_tracker(); ret = close(sock); - if (ret < 0) { + if (!ret) { + lttng_ust_delete_fd_from_tracker(sock); + } else { PERROR("close"); ret = -errno; } + lttng_ust_unlock_fd_tracker(); return ret; } @@ -606,8 +615,10 @@ ssize_t ustcomm_recv_channel_from_sessiond(int sock, goto error_recv; } /* recv wakeup fd */ + lttng_ust_lock_fd_tracker(); nr_fd = ustcomm_recv_fds_unix_sock(sock, &wakeup_fd, 1); if (nr_fd <= 0) { + lttng_ust_unlock_fd_tracker(); if (nr_fd < 0) { len = nr_fd; goto error_recv; @@ -617,6 +628,8 @@ ssize_t ustcomm_recv_channel_from_sessiond(int sock, } } *_wakeup_fd = wakeup_fd; + lttng_ust_add_fd_to_tracker(wakeup_fd); + lttng_ust_unlock_fd_tracker(); *_chan_data = chan_data; return len; @@ -636,8 +649,10 @@ int ustcomm_recv_stream_from_sessiond(int sock, int fds[2]; /* recv shm fd and wakeup fd */ + lttng_ust_lock_fd_tracker(); len = ustcomm_recv_fds_unix_sock(sock, fds, 2); if (len <= 0) { + lttng_ust_unlock_fd_tracker(); if (len < 0) { ret = len; goto error; @@ -648,6 +663,9 @@ int ustcomm_recv_stream_from_sessiond(int sock, } *shm_fd = fds[0]; *wakeup_fd = fds[1]; + lttng_ust_add_fd_to_tracker(fds[0]); + lttng_ust_add_fd_to_tracker(fds[1]); + lttng_ust_unlock_fd_tracker(); return 0; error: diff --git a/liblttng-ust-comm/lttng-ust-fd-tracker.c b/liblttng-ust-comm/lttng-ust-fd-tracker.c new file mode 100644 index 00000000..5a763ff2 --- /dev/null +++ b/liblttng-ust-comm/lttng-ust-fd-tracker.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2016 - Aravind HT + * 2016 - Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../liblttng-ust/compat.h" + +/* Operations on the fd set. */ +#define IS_FD_VALID(fd) ((fd) >= 0 && (fd) < lttng_ust_max_fd) +#define GET_FD_SET_FOR_FD(fd, fd_sets) (&((fd_sets)[(fd) / FD_SETSIZE])) +#define CALC_INDEX_TO_SET(fd) ((fd) % FD_SETSIZE) + +/* Check fd validity before calling these. */ +#define ADD_FD_TO_SET(fd, fd_sets) \ + FD_SET(CALC_INDEX_TO_SET(fd), GET_FD_SET_FOR_FD(fd, fd_sets)) +#define IS_FD_SET(fd, fd_sets) \ + FD_ISSET(CALC_INDEX_TO_SET(fd), GET_FD_SET_FOR_FD(fd, fd_sets)) +#define DEL_FD_FROM_SET(fd, fd_sets) \ + FD_CLR(CALC_INDEX_TO_SET(fd), GET_FD_SET_FOR_FD(fd, fd_sets)) + +/* + * Protect the lttng_fd_set. Nests within the ust_lock, and therefore + * within the libc dl lock. Therefore, we need to fixup the TLS before + * nesting into this lock. + */ +static pthread_mutex_t ust_safe_guard_fd_mutex = PTHREAD_MUTEX_INITIALIZER; +/* + * Track whether we are within lttng-ust or application, for close + * system call override by LD_PRELOAD library. + */ +static DEFINE_URCU_TLS(int, thread_fd_tracking); + +/* fd_set used to book keep fd being used by lttng-ust. */ +static fd_set *lttng_fd_set; +static int lttng_ust_max_fd; +static int num_fd_sets; + +/* + * Force a read (imply TLS fixup for dlopen) of TLS variables. + */ +void lttng_ust_fixup_fd_tracker_tls(void) +{ + asm volatile ("" : : "m" (URCU_TLS(thread_fd_tracking))); +} + +/* + * Allocate the fd set array based on the hard limit set for this + * process. This will be called during the constructor execution + * and will also be called in the child after fork via lttng_ust_init. + */ +void lttng_ust_init_fd_tracker(void) +{ + struct rlimit rlim; + int i; + + memset(&rlim, 0, sizeof(rlim)); + /* Get the current possible max number of fd for this process. */ + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) + abort(); + /* + * FD set array size determined using the hard limit. Even if + * the process wishes to increase its limit using setrlimit, it + * can only do so with the softlimit which will be less than the + * hard limit. + */ + lttng_ust_max_fd = rlim.rlim_max; + num_fd_sets = lttng_ust_max_fd / FD_SETSIZE; + if (lttng_ust_max_fd % FD_SETSIZE) + ++num_fd_sets; + if (lttng_fd_set != NULL) { + free(lttng_fd_set); + lttng_fd_set = NULL; + } + lttng_fd_set = malloc(num_fd_sets * (sizeof(fd_set))); + if (!lttng_fd_set) + abort(); + for (i = 0; i < num_fd_sets; i++) + FD_ZERO((<tng_fd_set[i])); +} + +void lttng_ust_lock_fd_tracker(void) +{ + URCU_TLS(thread_fd_tracking) = 1; + /* + * Ensure the compiler don't move the store after the close() + * call in case close() would be marked as leaf. + */ + cmm_barrier(); + pthread_mutex_lock(&ust_safe_guard_fd_mutex); +} + +void lttng_ust_unlock_fd_tracker(void) +{ + pthread_mutex_unlock(&ust_safe_guard_fd_mutex); + /* + * Ensure the compiler don't move the store before the close() + * call, in case close() would be marked as leaf. + */ + cmm_barrier(); + URCU_TLS(thread_fd_tracking) = 0; +} + +/* + * Needs to be called with ust_safe_guard_fd_mutex held when opening the fd. + * Has strict checking of fd validity. + */ +void lttng_ust_add_fd_to_tracker(int fd) +{ + assert(URCU_TLS(thread_fd_tracking)); + /* Trying to add an fd which we can not accommodate. */ + assert(IS_FD_VALID(fd)); + /* Setting an fd thats already set. */ + assert(!IS_FD_SET(fd, lttng_fd_set)); + + ADD_FD_TO_SET(fd, lttng_fd_set); +} + +/* + * Needs to be called with ust_safe_guard_fd_mutex held when opening the fd. + * Has strict checking for fd validity. + */ +void lttng_ust_delete_fd_from_tracker(int fd) +{ + assert(URCU_TLS(thread_fd_tracking)); + /* Not a valid fd. */ + assert(IS_FD_VALID(fd)); + /* Deleting an fd which was not set. */ + assert(IS_FD_SET(fd, lttng_fd_set)); + + DEL_FD_FROM_SET(fd, lttng_fd_set); +} + +/* + * Interface allowing applications to close arbitrary file descriptors. + * We check if it is owned by lttng-ust, and return -1, errno=EBADF + * instead of closing it if it is the case. + */ +int lttng_ust_safe_close_fd(int fd, int (*close_cb)(int fd)) +{ + int ret = 0; + + lttng_ust_fixup_fd_tracker_tls(); + + /* + * If called from lttng-ust, we directly call close without + * validating whether the FD is part of the tracked set. + */ + if (URCU_TLS(thread_fd_tracking)) + return close_cb(fd); + + lttng_ust_lock_fd_tracker(); + if (IS_FD_VALID(fd) && IS_FD_SET(fd, lttng_fd_set)) { + ret = -1; + errno = EBADF; + } else { + ret = close_cb(fd); + } + lttng_ust_unlock_fd_tracker(); + + return ret; +} + +#ifdef __OpenBSD__ +static void set_close_success(int *p) +{ + *p = 1; +} +static int test_close_success(const int *p) +{ + return *p; +} +#else +static void set_close_success(int *p __attribute__((unused))) +{ +} +static int test_close_success(const int *p __attribute__((unused))) +{ + return 1; +} +#endif + +/* + * Implement helper for closefrom() override. + */ +int lttng_ust_safe_closefrom_fd(int lowfd, int (*close_cb)(int fd)) +{ + int ret = 0, close_success = 0, i; + + lttng_ust_fixup_fd_tracker_tls(); + + if (lowfd < 0) { + /* + * NetBSD return EBADF if fd is invalid. + */ + errno = EBADF; + ret = -1; + goto end; + } + /* + * If called from lttng-ust, we directly call close without + * validating whether the FD is part of the tracked set. + */ + if (URCU_TLS(thread_fd_tracking)) { + for (i = lowfd; i < lttng_ust_max_fd; i++) { + if (close_cb(i) < 0) { + switch (errno) { + case EBADF: + continue; + case EINTR: + default: + ret = -1; + goto end; + } + } + set_close_success(&close_success); + } + } else { + lttng_ust_lock_fd_tracker(); + for (i = lowfd; i < lttng_ust_max_fd; i++) { + if (IS_FD_VALID(i) && IS_FD_SET(i, lttng_fd_set)) + continue; + if (close_cb(i) < 0) { + switch (errno) { + case EBADF: + continue; + case EINTR: + default: + ret = -1; + lttng_ust_unlock_fd_tracker(); + goto end; + } + } + set_close_success(&close_success); + } + lttng_ust_unlock_fd_tracker(); + } + if (!test_close_success(&close_success)) { + /* + * OpenBSD return EBADF if fd is greater than all open + * file descriptors. + */ + ret = -1; + errno = EBADF; + } +end: + return ret; +} diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index ac59d15a..4fbf15c6 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "tracepoint-internal.h" #include #include @@ -528,7 +529,9 @@ invalid: { int close_ret; + lttng_ust_lock_fd_tracker(); close_ret = close(wakeup_fd); + lttng_ust_unlock_fd_tracker(); if (close_ret) { PERROR("close"); } diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index dd8822cf..4a218663 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include "tracepoint-internal.h" @@ -404,6 +405,7 @@ void lttng_ust_fixup_tls(void) lttng_fixup_nest_count_tls(); lttng_fixup_procname_tls(); lttng_fixup_ust_mutex_nest_tls(); + lttng_ust_fixup_fd_tracker_tls(); } int lttng_get_notify_socket(void *owner) @@ -1231,17 +1233,28 @@ char *get_map_shm(struct sock_info *sock_info) goto error; } + lttng_ust_lock_fd_tracker(); wait_shm_fd = get_wait_shm(sock_info, page_size); if (wait_shm_fd < 0) { + lttng_ust_unlock_fd_tracker(); goto error; } + lttng_ust_add_fd_to_tracker(wait_shm_fd); + lttng_ust_unlock_fd_tracker(); + wait_shm_mmap = mmap(NULL, page_size, PROT_READ, MAP_SHARED, wait_shm_fd, 0); + /* close shm fd immediately after taking the mmap reference */ + lttng_ust_lock_fd_tracker(); ret = close(wait_shm_fd); - if (ret) { + if (!ret) { + lttng_ust_delete_fd_from_tracker(wait_shm_fd); + } else { PERROR("Error closing fd"); } + lttng_ust_unlock_fd_tracker(); + if (wait_shm_mmap == MAP_FAILED) { DBG("mmap error (can be caused by race with sessiond). Fallback to poll mode."); goto error; @@ -1351,6 +1364,7 @@ restart: } if (sock_info->socket != -1) { + /* FD tracker is updated by ustcomm_close_unix_sock() */ ret = ustcomm_close_unix_sock(sock_info->socket); if (ret) { ERR("Error closing %s ust cmd socket", @@ -1359,6 +1373,7 @@ restart: sock_info->socket = -1; } if (sock_info->notify_socket != -1) { + /* FD tracker is updated by ustcomm_close_unix_sock() */ ret = ustcomm_close_unix_sock(sock_info->notify_socket); if (ret) { ERR("Error closing %s ust notify socket", @@ -1367,6 +1382,10 @@ restart: sock_info->notify_socket = -1; } + if (ust_lock()) { + goto quit; + } + /* * Register. We need to perform both connect and sending * registration message before doing the next connect otherwise @@ -1375,16 +1394,14 @@ restart: * first connect registration message. */ /* Connect cmd socket */ + lttng_ust_lock_fd_tracker(); ret = ustcomm_connect_unix_sock(sock_info->sock_path, get_connect_sock_timeout()); if (ret < 0) { + lttng_ust_unlock_fd_tracker(); DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name); prev_connect_failed = 1; - if (ust_lock()) { - goto quit; - } - /* * If we cannot find the sessiond daemon, don't delay * constructor execution. @@ -1394,8 +1411,16 @@ restart: ust_unlock(); goto restart; } + lttng_ust_add_fd_to_tracker(ret); + lttng_ust_unlock_fd_tracker(); sock_info->socket = ret; + ust_unlock(); + /* + * Unlock/relock ust lock because connect is blocking (with + * timeout). Don't delay constructors on the ust lock for too + * long. + */ if (ust_lock()) { goto quit; } @@ -1430,18 +1455,24 @@ restart: } ust_unlock(); + /* + * Unlock/relock ust lock because connect is blocking (with + * timeout). Don't delay constructors on the ust lock for too + * long. + */ + if (ust_lock()) { + goto quit; + } /* Connect notify socket */ + lttng_ust_lock_fd_tracker(); ret = ustcomm_connect_unix_sock(sock_info->sock_path, get_connect_sock_timeout()); if (ret < 0) { + lttng_ust_unlock_fd_tracker(); DBG("Info: sessiond not accepting connections to %s apps socket", sock_info->name); prev_connect_failed = 1; - if (ust_lock()) { - goto quit; - } - /* * If we cannot find the sessiond daemon, don't delay * constructor execution. @@ -1451,8 +1482,20 @@ restart: ust_unlock(); goto restart; } + lttng_ust_add_fd_to_tracker(ret); + lttng_ust_unlock_fd_tracker(); sock_info->notify_socket = ret; + ust_unlock(); + /* + * Unlock/relock ust lock because connect is blocking (with + * timeout). Don't delay constructors on the ust lock for too + * long. + */ + if (ust_lock()) { + goto quit; + } + timeout = get_notify_sock_timeout(); if (timeout >= 0) { /* @@ -1475,10 +1518,6 @@ restart: WARN("Unsupported timeout value %ld", timeout); } - if (ust_lock()) { - goto quit; - } - ret = register_to_sessiond(sock_info->notify_socket, USTCTL_SOCKET_NOTIFY); if (ret < 0) { @@ -1608,6 +1647,7 @@ void __attribute__((constructor)) lttng_ust_init(void) */ init_usterr(); init_tracepoint(); + lttng_ust_init_fd_tracker(); lttng_ust_clock_init(); lttng_ust_getcpu_init(); lttng_ust_statedump_init(); diff --git a/libringbuffer/ring_buffer_frontend.c b/libringbuffer/ring_buffer_frontend.c index 07724b71..be20d69b 100644 --- a/libringbuffer/ring_buffer_frontend.c +++ b/libringbuffer/ring_buffer_frontend.c @@ -901,11 +901,12 @@ static void channel_print_errors(struct channel *chan, } static void channel_free(struct channel *chan, - struct lttng_ust_shm_handle *handle) + struct lttng_ust_shm_handle *handle, + int consumer) { channel_backend_free(&chan->backend, handle); /* chan is freed by shm teardown */ - shm_object_table_destroy(handle->table); + shm_object_table_destroy(handle->table, consumer); free(handle); } @@ -1028,7 +1029,7 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff error_backend_init: error_append: - shm_object_table_destroy(handle->table); + shm_object_table_destroy(handle->table, 1); error_table_alloc: free(handle); return NULL; @@ -1060,7 +1061,7 @@ struct lttng_ust_shm_handle *channel_handle_create(void *data, return handle; error_table_object: - shm_object_table_destroy(handle->table); + shm_object_table_destroy(handle->table, 0); error_table_alloc: free(handle); return NULL; @@ -1088,9 +1089,10 @@ unsigned int channel_handle_get_nr_streams(struct lttng_ust_shm_handle *handle) } static -void channel_release(struct channel *chan, struct lttng_ust_shm_handle *handle) +void channel_release(struct channel *chan, struct lttng_ust_shm_handle *handle, + int consumer) { - channel_free(chan, handle); + channel_free(chan, handle, consumer); } /** @@ -1122,7 +1124,7 @@ void channel_destroy(struct channel *chan, struct lttng_ust_shm_handle *handle, * sessiond/consumer are keeping a reference on the shm file * descriptor directly. No need to refcount. */ - channel_release(chan, handle); + channel_release(chan, handle, consumer); return; } diff --git a/libringbuffer/shm.c b/libringbuffer/shm.c index 86e84b3f..c4c651e4 100644 --- a/libringbuffer/shm.c +++ b/libringbuffer/shm.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * Ensure we have the required amount of space available by writing 0 @@ -343,7 +344,7 @@ error_fcntl: } static -void shmp_object_destroy(struct shm_object *obj) +void shmp_object_destroy(struct shm_object *obj, int consumer) { switch (obj->type) { case SHM_OBJECT_SHM: @@ -355,20 +356,46 @@ void shmp_object_destroy(struct shm_object *obj) PERROR("umnmap"); assert(0); } + if (obj->shm_fd_ownership) { - ret = close(obj->shm_fd); - if (ret) { - PERROR("close"); - assert(0); + /* Delete FDs only if called from app (not consumer). */ + if (!consumer) { + lttng_ust_lock_fd_tracker(); + ret = close(obj->shm_fd); + if (!ret) { + lttng_ust_delete_fd_from_tracker(obj->shm_fd); + } else { + PERROR("close"); + assert(0); + } + lttng_ust_unlock_fd_tracker(); + } else { + ret = close(obj->shm_fd); + if (ret) { + PERROR("close"); + assert(0); + } } } for (i = 0; i < 2; i++) { if (obj->wait_fd[i] < 0) continue; - ret = close(obj->wait_fd[i]); - if (ret) { - PERROR("close"); - assert(0); + if (!consumer) { + lttng_ust_lock_fd_tracker(); + ret = close(obj->wait_fd[i]); + if (!ret) { + lttng_ust_delete_fd_from_tracker(obj->wait_fd[i]); + } else { + PERROR("close"); + assert(0); + } + lttng_ust_unlock_fd_tracker(); + } else { + ret = close(obj->wait_fd[i]); + if (ret) { + PERROR("close"); + assert(0); + } } } break; @@ -380,10 +407,22 @@ void shmp_object_destroy(struct shm_object *obj) for (i = 0; i < 2; i++) { if (obj->wait_fd[i] < 0) continue; - ret = close(obj->wait_fd[i]); - if (ret) { - PERROR("close"); - assert(0); + if (!consumer) { + lttng_ust_lock_fd_tracker(); + ret = close(obj->wait_fd[i]); + if (!ret) { + lttng_ust_delete_fd_from_tracker(obj->wait_fd[i]); + } else { + PERROR("close"); + assert(0); + } + lttng_ust_unlock_fd_tracker(); + } else { + ret = close(obj->wait_fd[i]); + if (ret) { + PERROR("close"); + assert(0); + } } } free(obj->memory_map); @@ -394,12 +433,12 @@ void shmp_object_destroy(struct shm_object *obj) } } -void shm_object_table_destroy(struct shm_object_table *table) +void shm_object_table_destroy(struct shm_object_table *table, int consumer) { int i; for (i = 0; i < table->allocated_len; i++) - shmp_object_destroy(&table->objects[i]); + shmp_object_destroy(&table->objects[i], consumer); free(table); } diff --git a/libringbuffer/shm.h b/libringbuffer/shm.h index a6b9ed8a..355d4d98 100644 --- a/libringbuffer/shm.h +++ b/libringbuffer/shm.h @@ -96,7 +96,7 @@ struct shm_object *shm_object_table_append_shm(struct shm_object_table *table, /* mem ownership is passed to shm_object_table_append_mem(). */ struct shm_object *shm_object_table_append_mem(struct shm_object_table *table, void *mem, size_t memory_map_size, int wakeup_fd); -void shm_object_table_destroy(struct shm_object_table *table); +void shm_object_table_destroy(struct shm_object_table *table, int consumer); /* * zalloc_shm - allocate memory within a shm object.