* These declarations should NOT be considered stable API.
*/
+#include <stdio.h>
+
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_unlock_fd_tracker(void);
int lttng_ust_safe_close_fd(int fd, int (*close_cb)(int));
+int lttng_ust_safe_fclose_stream(FILE *stream, int (*fclose_cb)(FILE *stream));
int lttng_ust_safe_closefrom_fd(int lowfd, int (*close_cb)(int));
#endif /* _LTTNG_UST_FD_H */
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();
+
+ /*
+ * 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)
{
volatile enum ust_loglevel ust_loglevel;
static int (*__lttng_ust_fd_plibc_close)(int fd);
+static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream);
static
int _lttng_ust_fd_libc_close(int fd)
return lttng_ust_safe_close_fd(fd, __lttng_ust_fd_plibc_close);
}
+static
+int _lttng_ust_fd_libc_fclose(FILE *stream)
+{
+ if (!__lttng_ust_fd_plibc_fclose) {
+ __lttng_ust_fd_plibc_fclose = dlsym(RTLD_NEXT, "fclose");
+ if (!__lttng_ust_fd_plibc_fclose) {
+ fprintf(stderr, "%s\n", dlerror());
+ return -1;
+ }
+ }
+ return lttng_ust_safe_fclose_stream(stream,
+ __lttng_ust_fd_plibc_fclose);
+}
+
int close(int fd)
{
return _lttng_ust_fd_libc_close(fd);
}
+/*
+ * Note: fcloseall() is not an issue because it fcloses only the
+ * streams it knows about, which differs from the problems caused by
+ * gnulib close_stdout(), which does an explicit fclose(stdout).
+ */
+int fclose(FILE *stream)
+{
+ return _lttng_ust_fd_libc_fclose(stream);
+}
+
#if defined(__sun__) || defined(__FreeBSD__)
/* Solaris and FreeBSD. */
void closefrom(int lowfd)