X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Flttng-ust-fd%2Flttng-ust-fd.c;fp=src%2Flib%2Flttng-ust-fd%2Flttng-ust-fd.c;h=0360b6f269a85eca5db049bacf258492b7c97249;hb=4b01076fea0f635af6af6762a8edce1be03e5d39;hp=d2ebcfbc38be862b6effffdc490f7a7d0ce968cb;hpb=9c3f3d0208bab524c94466b8cc6bb1dcbc4a906b;p=lttng-ust.git diff --git a/src/lib/lttng-ust-fd/lttng-ust-fd.c b/src/lib/lttng-ust-fd/lttng-ust-fd.c index d2ebcfbc..0360b6f2 100644 --- a/src/lib/lttng-ust-fd/lttng-ust-fd.c +++ b/src/lib/lttng-ust-fd/lttng-ust-fd.c @@ -21,6 +21,8 @@ static int (*__lttng_ust_fd_plibc_close)(int fd) = NULL; static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream) = NULL; +static int (*__lttng_ust_fd_plibc_close_range)(unsigned int first, + unsigned int last, int flags) = NULL; /* * Use dlsym to find the original libc close() symbol and store it in @@ -60,6 +62,24 @@ void *_lttng_ust_fd_init_plibc_fclose(void) return __lttng_ust_fd_plibc_fclose; } +/* + * Use dlsym to find the original libc close_range() symbol and store it + * in __lttng_ust_fd_plibc_close_range. The close_range symbol only + * appears in glibc 2.34, so it is considered optional. + */ +static +void *_lttng_ust_fd_init_plibc_close_range(void) +{ + if (__lttng_ust_fd_plibc_close_range == NULL) { + __lttng_ust_fd_plibc_close_range = dlsym(RTLD_NEXT, "close_range"); + + if (__lttng_ust_fd_plibc_close_range == NULL) + __lttng_ust_fd_plibc_close_range = (void *) LTTNG_UST_DLSYM_FAILED_PTR; + } + + return __lttng_ust_fd_plibc_close_range; +} + static void _lttng_ust_fd_ctor(void) __attribute__((constructor)); @@ -75,6 +95,7 @@ void _lttng_ust_fd_ctor(void) */ (void) _lttng_ust_fd_init_plibc_close(); (void) _lttng_ust_fd_init_plibc_fclose(); + (void) _lttng_ust_fd_init_plibc_close_range(); } /* @@ -127,6 +148,30 @@ int fclose(FILE *stream) __lttng_ust_fd_plibc_fclose); } +/* + * Override the libc close_range() symbol with our own, allowing + * applications to close arbitrary file descriptors. If the fd is owned + * by lttng-ust, return -1, errno=EBADF instead of closing it. + * + * If dlsym failed to find the original libc close_range() symbol, + * return -1, errno=ENOSYS. + * + * There is a short window before the library constructor has executed where + * this wrapper could call dlsym() and thus not be async-signal-safe. + */ +int close_range(unsigned int first, unsigned int last, int flags) +{ + /* + * We can't retry dlsym here since close is async-signal-safe. + */ + if (_lttng_ust_fd_init_plibc_close_range() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) { + errno = ENOSYS; + return -1; + } + + return lttng_ust_safe_close_range_fd(first, last, flags, __lttng_ust_fd_plibc_close_range); +} + #if defined(__sun__) || defined(__FreeBSD__) /* Solaris and FreeBSD. */ void closefrom(int lowfd)