#include <pthread.h>
#include <urcu/compiler.h>
#include <urcu/tls-compat.h>
+#include <urcu/system.h>
#include <ust-fd.h>
#include <helper.h>
* Track whether we are within lttng-ust or application, for close
* system call override by LD_PRELOAD library.
*/
-static DEFINE_URCU_TLS_IE(int, thread_fd_tracking);
+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;
+static int init_done;
/*
* Force a read (imply TLS fixup for dlopen) of TLS variables.
struct rlimit rlim;
int i;
+ if (CMM_LOAD_SHARED(init_done))
+ return;
+
memset(&rlim, 0, sizeof(rlim));
/* Get the current possible max number of fd for this process. */
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
abort();
for (i = 0; i < num_fd_sets; i++)
FD_ZERO((<tng_fd_set[i]));
+ CMM_STORE_SHARED(init_done, 1);
}
void lttng_ust_lock_fd_tracker(void)
*/
void lttng_ust_add_fd_to_tracker(int fd)
{
+ /*
+ * Ensure the tracker is initialized when called from
+ * constructors.
+ */
+ lttng_ust_init_fd_tracker();
+
assert(URCU_TLS(thread_fd_tracking));
/* Trying to add an fd which we can not accommodate. */
assert(IS_FD_VALID(fd));
*/
void lttng_ust_delete_fd_from_tracker(int fd)
{
+ /*
+ * Ensure the tracker is initialized when called from
+ * constructors.
+ */
+ lttng_ust_init_fd_tracker();
+
assert(URCU_TLS(thread_fd_tracking));
/* Not a valid fd. */
assert(IS_FD_VALID(fd));
lttng_ust_fixup_fd_tracker_tls();
+ /*
+ * Ensure the tracker is initialized when called from
+ * constructors.
+ */
+ lttng_ust_init_fd_tracker();
+
/*
* If called from lttng-ust, we directly call close without
* validating whether the FD is part of the tracked set.
return ret;
}
+/*
+ * Interface allowing applications to close arbitrary streams.
+ * 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_fclose_stream(FILE *stream, int (*fclose_cb)(FILE *stream))
+{
+ int ret = 0, fd;
+
+ lttng_ust_fixup_fd_tracker_tls();
+
+ /*
+ * Ensure the tracker is initialized when called from
+ * constructors.
+ */
+ lttng_ust_init_fd_tracker();
+
+ /*
+ * If called from lttng-ust, we directly call fclose without
+ * validating whether the FD is part of the tracked set.
+ */
+ if (URCU_TLS(thread_fd_tracking))
+ return fclose_cb(stream);
+
+ fd = fileno(stream);
+
+ lttng_ust_lock_fd_tracker();
+ if (IS_FD_VALID(fd) && IS_FD_SET(fd, lttng_fd_set)) {
+ ret = -1;
+ errno = EBADF;
+ } else {
+ ret = fclose_cb(stream);
+ }
+ lttng_ust_unlock_fd_tracker();
+
+ return ret;
+}
+
#ifdef __OpenBSD__
static void set_close_success(int *p)
{
lttng_ust_fixup_fd_tracker_tls();
+ /*
+ * Ensure the tracker is initialized when called from
+ * constructors.
+ */
+ lttng_ust_init_fd_tracker();
+
if (lowfd < 0) {
/*
* NetBSD return EBADF if fd is invalid.