fix: handle EINTR correctly in get_cpu_mask_from_sysfs
[lttng-ust.git] / src / lib / lttng-ust-fd / lttng-ust-fd.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 */
6
7 #define _LGPL_SOURCE
8 #include <limits.h>
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <dlfcn.h>
13 #include <errno.h>
14
15 #include <lttng/ust-common.h>
16
17 #include "common/macros.h"
18 #include "common/ust-fd.h"
19
20 #define LTTNG_UST_DLSYM_FAILED_PTR 0x1
21
22 static int (*__lttng_ust_fd_plibc_close)(int fd) = NULL;
23 static int (*__lttng_ust_fd_plibc_fclose)(FILE *stream) = NULL;
24 static int (*__lttng_ust_fd_plibc_close_range)(unsigned int first,
25 unsigned int last, int flags) = NULL;
26
27 /*
28 * Use dlsym to find the original libc close() symbol and store it in
29 * __lttng_ust_fd_plibc_close.
30 */
31 static
32 void *_lttng_ust_fd_init_plibc_close(void)
33 {
34 if (__lttng_ust_fd_plibc_close == NULL) {
35 __lttng_ust_fd_plibc_close = dlsym(RTLD_NEXT, "close");
36
37 if (__lttng_ust_fd_plibc_close == NULL) {
38 __lttng_ust_fd_plibc_close = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
39 fprintf(stderr, "%s\n", dlerror());
40 }
41 }
42
43 return __lttng_ust_fd_plibc_close;
44 }
45
46 /*
47 * Use dlsym to find the original libc fclose() symbol and store it in
48 * __lttng_ust_fd_plibc_fclose.
49 */
50 static
51 void *_lttng_ust_fd_init_plibc_fclose(void)
52 {
53 if (__lttng_ust_fd_plibc_fclose == NULL) {
54 __lttng_ust_fd_plibc_fclose = dlsym(RTLD_NEXT, "fclose");
55
56 if (__lttng_ust_fd_plibc_fclose == NULL) {
57 __lttng_ust_fd_plibc_fclose = (void *) LTTNG_UST_DLSYM_FAILED_PTR;
58 fprintf(stderr, "%s\n", dlerror());
59 }
60 }
61
62 return __lttng_ust_fd_plibc_fclose;
63 }
64
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 */
70 static
71 void *_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
83 static
84 void _lttng_ust_fd_ctor(void)
85 __attribute__((constructor));
86 static
87 void _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();
98 (void) _lttng_ust_fd_init_plibc_close_range();
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 */
112 int close(int fd)
113 {
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);
123 }
124
125 /*
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).
139 */
140 int fclose(FILE *stream)
141 {
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);
149 }
150
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 */
162 int 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
175 #if defined(__sun__) || defined(__FreeBSD__)
176 /* Solaris and FreeBSD. */
177 void closefrom(int lowfd)
178 {
179 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
180 return;
181 }
182
183 (void) lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
184 }
185 #elif defined(__NetBSD__) || defined(__OpenBSD__)
186 /* NetBSD and OpenBSD. */
187 int closefrom(int lowfd)
188 {
189 if (_lttng_ust_fd_init_plibc_close() == (void *) LTTNG_UST_DLSYM_FAILED_PTR) {
190 errno = ENOSYS;
191 return -1;
192 }
193
194 return lttng_ust_safe_closefrom_fd(lowfd, __lttng_ust_fd_plibc_close);
195 }
196 #else
197 /* As far as we know, this OS does not implement closefrom. */
198 #endif
This page took 0.033244 seconds and 4 git commands to generate.