X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust-comm%2Flttng-ust-fd-tracker.c;h=42c3984cc2d3a390f941005f82a0315aa329c208;hb=48a143c09cc97bf7a2ace811277e7d60b294b5f6;hp=1118163a201af456ac6ed28d490e09f458af08ef;hpb=283f4bec47781f7a39dde82d02e53add02155f9c;p=lttng-ust.git diff --git a/liblttng-ust-comm/lttng-ust-fd-tracker.c b/liblttng-ust-comm/lttng-ust-fd-tracker.c index 1118163a..42c3984c 100644 --- a/liblttng-ust-comm/lttng-ust-fd-tracker.c +++ b/liblttng-ust-comm/lttng-ust-fd-tracker.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -75,10 +77,20 @@ static int ust_safe_guard_saved_cancelstate; /* * Track whether we are within lttng-ust or application, for close - * system call override by LD_PRELOAD library. + * system call override by LD_PRELOAD library. Threads registered + * as being lttng-ust listener threads need to perform fd tracker + * locking explicitly around their use of file descriptor manipulation + * functions. */ static DEFINE_URCU_TLS(int, thread_fd_tracking); +/* + * Track whether we are invoking close() from a signal handler nested on + * an application thread. + */ +static DEFINE_URCU_TLS(int, ust_fd_mutex_nest); + + /* fd_set used to book keep fd being used by lttng-ust. */ static fd_set *lttng_fd_set; static int lttng_ust_max_fd; @@ -91,6 +103,7 @@ static int init_done; void lttng_ust_fixup_fd_tracker_tls(void) { asm volatile ("" : : "m" (URCU_TLS(thread_fd_tracking))); + asm volatile ("" : : "m" (URCU_TLS(ust_fd_mutex_nest))); } /* @@ -134,37 +147,63 @@ void lttng_ust_init_fd_tracker(void) void lttng_ust_lock_fd_tracker(void) { + sigset_t sig_all_blocked, orig_mask; int ret, oldstate; ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); if (ret) { ERR("pthread_setcancelstate: %s", strerror(ret)); } - 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); - ust_safe_guard_saved_cancelstate = oldstate; + sigfillset(&sig_all_blocked); + ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask); + if (ret) { + ERR("pthread_sigmask: %s", strerror(ret)); + } + if (!URCU_TLS(ust_fd_mutex_nest)++) { + /* + * 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); + ust_safe_guard_saved_cancelstate = oldstate; + } + ret = pthread_sigmask(SIG_SETMASK, &orig_mask, NULL); + if (ret) { + ERR("pthread_sigmask: %s", strerror(ret)); + } } void lttng_ust_unlock_fd_tracker(void) { + sigset_t sig_all_blocked, orig_mask; int ret, newstate, oldstate; + bool restore_cancel = false; - newstate = ust_safe_guard_saved_cancelstate; - pthread_mutex_unlock(&ust_safe_guard_fd_mutex); + sigfillset(&sig_all_blocked); + ret = pthread_sigmask(SIG_SETMASK, &sig_all_blocked, &orig_mask); + if (ret) { + ERR("pthread_sigmask: %s", strerror(ret)); + } /* * 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; - ret = pthread_setcancelstate(newstate, &oldstate); + if (!--URCU_TLS(ust_fd_mutex_nest)) { + newstate = ust_safe_guard_saved_cancelstate; + restore_cancel = true; + pthread_mutex_unlock(&ust_safe_guard_fd_mutex); + } + ret = pthread_sigmask(SIG_SETMASK, &orig_mask, NULL); if (ret) { - ERR("pthread_setcancelstate: %s", strerror(ret)); + ERR("pthread_sigmask: %s", strerror(ret)); + } + if (restore_cancel) { + ret = pthread_setcancelstate(newstate, &oldstate); + if (ret) { + ERR("pthread_setcancelstate: %s", strerror(ret)); + } } } @@ -255,7 +294,7 @@ int lttng_ust_add_fd_to_tracker(int fd) * constructors. */ lttng_ust_init_fd_tracker(); - assert(URCU_TLS(thread_fd_tracking)); + assert(URCU_TLS(ust_fd_mutex_nest)); if (IS_FD_STD(fd)) { ret = dup_std_fd(fd); @@ -288,7 +327,7 @@ void lttng_ust_delete_fd_from_tracker(int fd) */ lttng_ust_init_fd_tracker(); - assert(URCU_TLS(thread_fd_tracking)); + assert(URCU_TLS(ust_fd_mutex_nest)); /* Not a valid fd. */ assert(IS_FD_VALID(fd)); /* Deleting an fd which was not set. */ @@ -462,3 +501,8 @@ int lttng_ust_safe_closefrom_fd(int lowfd, int (*close_cb)(int fd)) end: return ret; } + +void lttng_ust_fd_tracker_register_thread(void) +{ + URCU_TLS(thread_fd_tracking) = 1; +}