fix: handle EINTR correctly in get_cpu_mask_from_sysfs
[lttng-ust.git] / src / lib / lttng-ust-fd / lttng-ust-fd.c
CommitLineData
95e6d268 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
95e6d268 3 *
c0c0989a 4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
95e6d268
MD
5 */
6
95e6d268
MD
7#define _LGPL_SOURCE
8#include <limits.h>
9#include <stdio.h>
10#include <sys/types.h>
11#include <unistd.h>
95e6d268 12#include <dlfcn.h>
58048764 13#include <errno.h>
95e6d268 14
fca97dfd
MJ
15#include <lttng/ust-common.h>
16
9d315d6d 17#include "common/macros.h"
fca97dfd 18#include "common/ust-fd.h"
95e6d268 19
58048764 20#define LTTNG_UST_DLSYM_FAILED_PTR 0x1
95e6d268 21
58048764
MJ
22static int (*__lttng_ust_fd_plibc_close)(int fd) = NULL;
23static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream) = NULL;
4b01076f
MD
24static int (*__lttng_ust_fd_plibc_close_range)(unsigned int first,
25 unsigned int last, int flags) = NULL;
fca97dfd 26
58048764
MJ
27/*
28 * Use dlsym to find the original libc close() symbol and store it in
29 * __lttng_ust_fd_plibc_close.
30 */
95e6d268 31static
58048764 32void *_lttng_ust_fd_init_plibc_close(void)
95e6d268 33{
58048764 34 if (__lttng_ust_fd_plibc_close == NULL) {
95e6d268 35 __lttng_ust_fd_plibc_close = dlsym(RTLD_NEXT, "close");
58048764
MJ
36
37 if (__lttng_ust_fd_plibc_close == NULL) {
38 __lttng_ust_fd_plibc_close = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
95e6d268 39 fprintf(stderr, "%s\n", dlerror());
95e6d268
MD
40 }
41 }
58048764
MJ
42
43 return __lttng_ust_fd_plibc_close;
95e6d268
MD
44}
45
58048764
MJ
46/*
47 * Use dlsym to find the original libc fclose() symbol and store it in
48 * __lttng_ust_fd_plibc_fclose.
49 */
52a20dc7 50static
58048764 51void *_lttng_ust_fd_init_plibc_fclose(void)
52a20dc7 52{
58048764 53 if (__lttng_ust_fd_plibc_fclose == NULL) {
52a20dc7 54 __lttng_ust_fd_plibc_fclose = dlsym(RTLD_NEXT, "fclose");
58048764
MJ
55
56 if (__lttng_ust_fd_plibc_fclose == NULL) {
57 __lttng_ust_fd_plibc_fclose = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
52a20dc7 58 fprintf(stderr, "%s\n", dlerror());
52a20dc7
MD
59 }
60 }
58048764
MJ
61
62 return __lttng_ust_fd_plibc_fclose;
52a20dc7
MD
63}
64
4b01076f
MD
65/*
66 * Use dlsym to find the original libc close_range() symbol and store it
67 * in __lttng_ust_fd_plibc_close_range. The close_range symbol only
68 * appears in glibc 2.34, so it is considered optional.
69 */
70static
71void *_lttng_ust_fd_init_plibc_close_range(void)
72{
73 if (__lttng_ust_fd_plibc_close_range == NULL) {
74 __lttng_ust_fd_plibc_close_range = dlsym(RTLD_NEXT, "close_range");
75
76 if (__lttng_ust_fd_plibc_close_range == NULL)
77 __lttng_ust_fd_plibc_close_range = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
78 }
79
80 return __lttng_ust_fd_plibc_close_range;
81}
82
58048764
MJ
83static
84void _lttng_ust_fd_ctor(void)
85 __attribute__((constructor));
86static
87void _lttng_ust_fd_ctor(void)
88{
89 lttng_ust_common_ctor();
90
91 /*
92 * Initialize the function pointers to the original libc symbols in the
93 * constructor since close() has to stay async-signal-safe and as such,
94 * we can't call dlsym() in the override functions.
95 */
96 (void) _lttng_ust_fd_init_plibc_close();
97 (void) _lttng_ust_fd_init_plibc_fclose();
4b01076f 98 (void) _lttng_ust_fd_init_plibc_close_range();
58048764
MJ
99}
100
101/*
102 * Override the libc close() symbol with our own, allowing applications to
103 * close arbitrary file descriptors. If the fd is owned by lttng-ust, return
104 * -1, errno=EBADF instead of closing it.
105 *
106 * If dlsym failed to find the original libc close() symbol, return -1,
107 * errno=ENOSYS.
108 *
109 * There is a short window before the library constructor has executed where
110 * this wrapper could call dlsym() and thus not be async-signal-safe.
111 */
95e6d268
MD
112int close(int fd)
113{
58048764
MJ
114 /*
115 * We can't retry dlsym here since close is async-signal-safe.
116 */
117 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
118 errno = ENOSYS;
119 return -1;
120 }
121
122 return lttng_ust_safe_close_fd(fd, __lttng_ust_fd_plibc_close);
95e6d268
MD
123}
124
52a20dc7 125/*
58048764
MJ
126 * Override the libc fclose() symbol with our own, allowing applications to
127 * close arbitrary streams. If the fd is owned by lttng-ust, return -1,
128 * errno=EBADF instead of closing it.
129 *
130 * If dlsym failed to find the original libc close() symbol, return -1,
131 * errno=ENOSYS.
132 *
133 * There is a short window before the library constructor has executed where
134 * this wrapper could call dlsym() and thus not be async-signal-safe.
135 *
136 * Note: fcloseall() is not an issue because it closes only the streams it
137 * knows about, which differs from the problems caused by gnulib
138 * close_stdout(), which does an explicit fclose(stdout).
52a20dc7
MD
139 */
140int fclose(FILE *stream)
141{
58048764
MJ
142 if (_lttng_ust_fd_init_plibc_fclose() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
143 errno = ENOSYS;
144 return -1;
145 }
146
147 return lttng_ust_safe_fclose_stream(stream,
148 __lttng_ust_fd_plibc_fclose);
52a20dc7
MD
149}
150
4b01076f
MD
151/*
152 * Override the libc close_range() symbol with our own, allowing
153 * applications to close arbitrary file descriptors. If the fd is owned
154 * by lttng-ust, return -1, errno=EBADF instead of closing it.
155 *
156 * If dlsym failed to find the original libc close_range() symbol,
157 * return -1, errno=ENOSYS.
158 *
159 * There is a short window before the library constructor has executed where
160 * this wrapper could call dlsym() and thus not be async-signal-safe.
161 */
162int close_range(unsigned int first, unsigned int last, int flags)
163{
164 /*
165 * We can't retry dlsym here since close is async-signal-safe.
166 */
167 if (_lttng_ust_fd_init_plibc_close_range() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
168 errno = ENOSYS;
169 return -1;
170 }
171
172 return lttng_ust_safe_close_range_fd(first, last, flags, __lttng_ust_fd_plibc_close_range);
173}
174
95e6d268
MD
175#if defined(__sun__) || defined(__FreeBSD__)
176/* Solaris and FreeBSD. */
177void closefrom(int lowfd)
178{
58048764
MJ
179 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
180 return;
181 }
182
23366626 183 (void) lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
95e6d268
MD
184}
185#elif defined(__NetBSD__) || defined(__OpenBSD__)
186/* NetBSD and OpenBSD. */
187int closefrom(int lowfd)
188{
58048764
MJ
189 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
190 errno = ENOSYS;
191 return -1;
192 }
193
23366626 194 return lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
95e6d268
MD
195}
196#else
197/* As far as we know, this OS does not implement closefrom. */
198#endif
This page took 0.039449 seconds and 4 git commands to generate.