Skip to content

Commit 5b138a2

Browse files
cleanup: Improve portability
Co-authored-by: taylor.fish <[email protected]>
1 parent bc38307 commit 5b138a2

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

Sources/libreprl/libreprl-posix.c

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,21 @@
3535
#include <sys/resource.h>
3636
#include <sys/time.h>
3737
#include <sys/types.h>
38+
#include <sys/utsname.h>
3839
#include <sys/wait.h>
3940
#include <time.h>
4041
#include <unistd.h>
42+
4143
#ifdef __linux__
42-
#include <sys/utsname.h>
44+
# ifdef __has_include
45+
# if __has_include(<linux/close_range.h>)
46+
# define HAS_CLOSE_RANGE_HEADERS
47+
# endif
48+
# elif defined(__FreeBSD__)
49+
# ifdef CLOSE_RANGE_CLOEXEC
50+
# define HAS_CLOSE_RANGE_HEADERS
51+
# endif
52+
# endif
4353
#endif
4454

4555
// Well-known file descriptor numbers for reprl <-> child communication, child process side
@@ -60,6 +70,7 @@ static const int reprl_fds[] = {
6070
#define REPRL_MAX_TIMEOUT_IN_MICROSECONDS ((uint64_t)(INT_MAX) * 1000)
6171

6272
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
73+
6374
static size_t min(size_t x, size_t y) {
6475
return x < y ? x : y;
6576
}
@@ -93,29 +104,20 @@ static void free_string_array(char** arr)
93104
free(arr);
94105
}
95106

96-
static unsigned int getdtablesize_or_crash() {
107+
static int getdtablesize_or_crash() {
97108
const int tablesize = getdtablesize();
98109
if (tablesize < 0) {
99110
fprintf(stderr, "getdtablesize() failed: %s. This likely means the system is borked.\n",
100111
strerror(errno));
101-
exit(-1);
102-
}
103-
104-
return (unsigned int)tablesize;
105-
}
106-
107-
static int fd_cast(unsigned int fd) {
108-
if (fd > INT_MAX) {
109-
fprintf(stderr, "File descriptor value %u is too large to fit into int. This likely means "
110-
"the system is borked.\n", fd);
111-
exit(-1);
112+
abort();
112113
}
113114

114-
return (int)fd;
115+
return tablesize;
115116
}
116117

117118
static bool system_supports_close_range() {
118-
#ifdef __linux__
119+
#ifdef HAS_CLOSE_RANGE_HEADERS
120+
# ifdef __linux__
119121
struct utsname buffer;
120122
int major, minor, patch;
121123
(void)uname(&buffer); // Linux uname can only throw EFAULT if buf is invalid.
@@ -125,11 +127,16 @@ static bool system_supports_close_range() {
125127
}
126128

127129
return major > 5 || (major == 5 && minor >= 9);
128-
#else
130+
# elif defined(__FreeBSD__)
129131
// TODO: Technically, FreeBSD does support close_range, but I don't need support for it right
130-
// now, so leaving this unimplemented.
132+
// now, so leaving this unimplemented. Don't have a platform to test on.
131133
// https://man.freebsd.org/cgi/man.cgi?close_range(2)
132134
return false;
135+
# else
136+
return false;
137+
# endif
138+
#else
139+
return false;
133140
#endif
134141
}
135142

@@ -141,13 +148,14 @@ static int fd_qsort_compare(const void* a, const void* b) {
141148

142149
/// Fast path which uses close_range() to close ranges of fds.
143150
static void close_all_non_reprl_fds_fast() {
151+
#ifdef HAS_CLOSE_RANGE_HEADERS
144152
// Unfortunately we cannot trust the reprl_fds array to be sorted since an accidental edit to
145153
// reprl_fds could have broken that assumption. So let's create a new sorted array. It's cheap
146154
// anyways.
147155
int sorted_reprl_fds[ARRAY_SIZE(reprl_fds) + 2];
148156
sorted_reprl_fds[0] = 3; // Skip the well-known stdin, stdout, stderr fds.
149157
memcpy(sorted_reprl_fds + 1, reprl_fds, sizeof(reprl_fds));
150-
sorted_reprl_fds[ARRAY_SIZE(sorted_reprl_fds) - 1] = fd_cast(getdtablesize_or_crash());
158+
sorted_reprl_fds[ARRAY_SIZE(sorted_reprl_fds) - 1] = getdtablesize_or_crash();
151159
qsort(sorted_reprl_fds, ARRAY_SIZE(sorted_reprl_fds), sizeof(int), fd_qsort_compare);
152160

153161
// Cool, now we will iterate the sorted fds in ranges and close everything in between.
@@ -160,11 +168,16 @@ static void close_all_non_reprl_fds_fast() {
160168
}
161169
start_fd = end_fd + 1;
162170
}
171+
#else
172+
fprintf(stderr, "close_all_non_reprl_fds_fast() called on a system which does not support "
173+
"close_range(). This is likely a programming bug.\n");
174+
abort();
175+
#endif
163176
}
164177

165178
/// Fallback path which makes a close() syscall for each non-REPRL fd.
166179
static void close_all_non_reprl_fds_slow() {
167-
const int tablesize = fd_cast(getdtablesize_or_crash());
180+
const int tablesize = getdtablesize_or_crash();
168181

169182
for (int i = 3; i < tablesize; i++) {
170183
bool is_reprl_fd = false;
@@ -183,11 +196,7 @@ static void close_all_non_reprl_fds_slow() {
183196

184197
/// Close all file descriptors except the well-known REPRL and stdio fds.
185198
static void close_all_non_reprl_fds() {
186-
if (system_supports_close_range()) {
187-
close_all_non_reprl_fds_fast();
188-
} else {
189-
close_all_non_reprl_fds_slow();
190-
}
199+
system_supports_close_range() ? close_all_non_reprl_fds_fast() : close_all_non_reprl_fds_slow();
191200
}
192201

193202
// A unidirectional communication channel for larger amounts of data, up to a maximum size (REPRL_MAX_DATA_SIZE).

0 commit comments

Comments
 (0)