1 /*
2 * Copyright (c) 2015 DeNA Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22 #include <fcntl.h>
23 #include "cloexec.h"
24
25 pthread_mutex_t cloexec_mutex = PTHREAD_MUTEX_INITIALIZER;
26
set_cloexec(int fd)27 static int set_cloexec(int fd)
28 {
29 return fcntl(fd, F_SETFD, FD_CLOEXEC) != -1 ? 0 : -1;
30 }
31
32 /*
33 * note: the socket must be in non-blocking mode, or the call might block while the mutex is being locked
34 */
cloexec_accept(int socket,struct sockaddr * addr,socklen_t * addrlen)35 int cloexec_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
36 {
37 int fd;
38 pthread_mutex_lock(&cloexec_mutex);
39
40 if ((fd = accept(socket, addr, addrlen)) == -1)
41 goto Exit;
42 if (set_cloexec(fd) != 0) {
43 close(fd);
44 fd = -1;
45 goto Exit;
46 }
47
48 Exit:
49 pthread_mutex_unlock(&cloexec_mutex);
50 return fd;
51 }
52
cloexec_pipe(int fds[2])53 int cloexec_pipe(int fds[2])
54 {
55 #ifdef __linux__
56 #ifndef _GNU_SOURCE
57 extern int pipe2(int pipefd[2], int flags);
58 #endif
59 return pipe2(fds, O_CLOEXEC);
60 #else
61 int ret = -1;
62 pthread_mutex_lock(&cloexec_mutex);
63
64 if (pipe(fds) != 0)
65 goto Exit;
66 if (set_cloexec(fds[0]) != 0 || set_cloexec(fds[1]) != 0)
67 goto Exit;
68 ret = 0;
69
70 Exit:
71 pthread_mutex_unlock(&cloexec_mutex);
72 return ret;
73 #endif
74 }
75
cloexec_socket(int domain,int type,int protocol)76 int cloexec_socket(int domain, int type, int protocol)
77 {
78 #ifdef __linux__
79 return socket(domain, type | SOCK_CLOEXEC, protocol);
80 #else
81 int fd = -1;
82 pthread_mutex_lock(&cloexec_mutex);
83
84 if ((fd = socket(domain, type, protocol)) == -1)
85 goto Exit;
86 if (set_cloexec(fd) != 0) {
87 close(fd);
88 fd = -1;
89 goto Exit;
90 }
91
92 Exit:
93 pthread_mutex_unlock(&cloexec_mutex);
94 return fd;
95 #endif
96 }
97