1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| | /*
* Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
* License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
*/
#include "cmogstored.h"
bool mog_cloexec_atomic;
/*
* The presence of O_CLOEXEC in headers doesn't mean the kernel supports it
*/
#if defined(O_CLOEXEC) && (O_CLOEXEC != 0) && \
defined(SOCK_CLOEXEC) && \
defined(HAVE_ACCEPT4)
__attribute__((constructor)) static void cloexec_detect(void)
{
int flags;
int fd = open("/dev/null", O_RDONLY|O_CLOEXEC);
if (fd < 0) {
if (errno == EINVAL) goto out;
die_errno("open(/dev/null) failed");
}
flags = fcntl(fd, F_GETFD);
if (flags != -1)
mog_cloexec_atomic = ((flags & FD_CLOEXEC) == FD_CLOEXEC);
mog_close(fd);
if (! mog_cloexec_atomic) goto out;
/* try to ensure sockets are sane, too */
fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (fd < 0) {
if (errno == EINVAL) goto out;
die_errno("socket(AF_INET, ...) failed");
}
flags = fcntl(fd, F_GETFD);
if (flags != -1)
mog_cloexec_atomic = ((flags & FD_CLOEXEC) == FD_CLOEXEC);
mog_close(fd);
out:
if (mog_cloexec_atomic)
mog_cloexec_works();
else
warn("close-on-exec is NOT atomic");
}
#endif /* no O_CLOEXEC at all */
|