Commit | Line | Data |
---|---|---|
4b0e08be OP |
1 | diff --git a/auto/unix b/auto/unix |
2 | index 10835f6c..b5b33bb3 100644 | |
3 | --- a/auto/unix | |
4 | +++ b/auto/unix | |
5 | @@ -990,3 +990,27 @@ ngx_feature_test='struct addrinfo *res; | |
6 | if (getaddrinfo("localhost", NULL, NULL, &res) != 0) return 1; | |
7 | freeaddrinfo(res)' | |
8 | . auto/feature | |
9 | + | |
10 | +ngx_feature="SOCK_CLOEXEC support" | |
11 | +ngx_feature_name="NGX_HAVE_SOCKET_CLOEXEC" | |
12 | +ngx_feature_run=no | |
13 | +ngx_feature_incs="#include <sys/types.h> | |
14 | + #include <sys/socket.h>" | |
15 | +ngx_feature_path= | |
16 | +ngx_feature_libs= | |
17 | +ngx_feature_test="int fd; | |
18 | + fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);" | |
19 | +. auto/feature | |
20 | + | |
21 | +ngx_feature="FD_CLOEXEC support" | |
22 | +ngx_feature_name="NGX_HAVE_FD_CLOEXEC" | |
23 | +ngx_feature_run=no | |
24 | +ngx_feature_incs="#include <sys/types.h> | |
25 | + #include <sys/socket.h> | |
26 | + #include <fcntl.h>" | |
27 | +ngx_feature_path= | |
28 | +ngx_feature_libs= | |
29 | +ngx_feature_test="int fd; | |
30 | + fd = socket(AF_INET, SOCK_STREAM, 0); | |
31 | + fcntl(fd, F_SETFD, FD_CLOEXEC);" | |
32 | +. auto/feature | |
33 | diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c | |
34 | index cd55520c..438e0806 100644 | |
35 | --- a/src/core/ngx_resolver.c | |
36 | +++ b/src/core/ngx_resolver.c | |
37 | @@ -4466,8 +4466,14 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec) | |
38 | ngx_event_t *rev, *wev; | |
39 | ngx_connection_t *c; | |
40 | ||
41 | +#if (NGX_HAVE_SOCKET_CLOEXEC) | |
42 | + s = ngx_socket(rec->sockaddr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0); | |
43 | + | |
44 | +#else | |
45 | s = ngx_socket(rec->sockaddr->sa_family, SOCK_STREAM, 0); | |
46 | ||
47 | +#endif | |
48 | + | |
49 | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "TCP socket %d", s); | |
50 | ||
51 | if (s == (ngx_socket_t) -1) { | |
52 | @@ -4494,6 +4500,15 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec) | |
53 | goto failed; | |
54 | } | |
55 | ||
56 | +#if (NGX_HAVE_FD_CLOEXEC) | |
57 | + if (ngx_cloexec(s) == -1) { | |
58 | + ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno, | |
59 | + ngx_cloexec_n " failed"); | |
60 | + | |
61 | + goto failed; | |
62 | + } | |
63 | +#endif | |
64 | + | |
65 | rev = c->read; | |
66 | wev = c->write; | |
67 | ||
68 | diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h | |
69 | index 19fec68..8c2f01a 100644 | |
70 | --- a/src/event/ngx_event.h | |
71 | +++ b/src/event/ngx_event.h | |
72 | @@ -73,6 +73,9 @@ struct ngx_event_s { | |
73 | /* to test on worker exit */ | |
74 | unsigned channel:1; | |
75 | unsigned resolver:1; | |
76 | +#if (HAVE_SOCKET_CLOEXEC_PATCH) | |
77 | + unsigned skip_socket_leak_check:1; | |
78 | +#endif | |
79 | ||
80 | unsigned cancelable:1; | |
81 | ||
82 | diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c | |
83 | index 77563709..5827b9d0 100644 | |
84 | --- a/src/event/ngx_event_accept.c | |
85 | +++ b/src/event/ngx_event_accept.c | |
86 | @@ -62,7 +62,9 @@ ngx_event_accept(ngx_event_t *ev) | |
87 | ||
88 | #if (NGX_HAVE_ACCEPT4) | |
89 | if (use_accept4) { | |
90 | - s = accept4(lc->fd, &sa.sockaddr, &socklen, SOCK_NONBLOCK); | |
91 | + s = accept4(lc->fd, &sa.sockaddr, &socklen, | |
92 | + SOCK_NONBLOCK | SOCK_CLOEXEC); | |
93 | + | |
94 | } else { | |
95 | s = accept(lc->fd, &sa.sockaddr, &socklen); | |
96 | } | |
97 | @@ -202,6 +204,16 @@ ngx_event_accept(ngx_event_t *ev) | |
98 | ngx_close_accepted_connection(c); | |
99 | return; | |
100 | } | |
101 | + | |
102 | +#if (NGX_HAVE_FD_CLOEXEC) | |
103 | + if (ngx_cloexec(s) == -1) { | |
104 | + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, | |
105 | + ngx_cloexec_n " failed"); | |
106 | + ngx_close_accepted_connection(c); | |
107 | + return; | |
108 | + } | |
109 | +#endif | |
110 | + | |
111 | } | |
112 | } | |
113 | ||
114 | diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c | |
115 | index c5bb8068..cf33b1d2 100644 | |
116 | --- a/src/event/ngx_event_connect.c | |
117 | +++ b/src/event/ngx_event_connect.c | |
118 | @@ -38,8 +38,15 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) | |
119 | ||
120 | type = (pc->type ? pc->type : SOCK_STREAM); | |
121 | ||
122 | +#if (NGX_HAVE_SOCKET_CLOEXEC) | |
123 | + s = ngx_socket(pc->sockaddr->sa_family, type | SOCK_CLOEXEC, 0); | |
124 | + | |
125 | +#else | |
126 | s = ngx_socket(pc->sockaddr->sa_family, type, 0); | |
127 | ||
128 | +#endif | |
129 | + | |
130 | + | |
131 | ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pc->log, 0, "%s socket %d", | |
132 | (type == SOCK_STREAM) ? "stream" : "dgram", s); | |
133 | ||
134 | @@ -80,6 +87,15 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) | |
135 | goto failed; | |
136 | } | |
137 | ||
138 | +#if (NGX_HAVE_FD_CLOEXEC) | |
139 | + if (ngx_cloexec(s) == -1) { | |
140 | + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, | |
141 | + ngx_cloexec_n " failed"); | |
142 | + | |
143 | + goto failed; | |
144 | + } | |
145 | +#endif | |
146 | + | |
147 | if (pc->local) { | |
148 | ||
149 | #if (NGX_HAVE_TRANSPARENT_PROXY) | |
150 | diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c | |
151 | index c4376a5..48e8fa8 100644 | |
152 | --- a/src/os/unix/ngx_process_cycle.c | |
153 | +++ b/src/os/unix/ngx_process_cycle.c | |
154 | @@ -1032,6 +1032,9 @@ ngx_worker_process_exit(ngx_cycle_t *cycle) | |
155 | for (i = 0; i < cycle->connection_n; i++) { | |
156 | if (c[i].fd != -1 | |
157 | && c[i].read | |
158 | +#if (HAVE_SOCKET_CLOEXEC_PATCH) | |
159 | + && !c[i].read->skip_socket_leak_check | |
160 | +#endif | |
161 | && !c[i].read->accept | |
162 | && !c[i].read->channel | |
163 | && !c[i].read->resolver) | |
164 | diff --git a/src/os/unix/ngx_socket.h b/src/os/unix/ngx_socket.h | |
165 | index fcc51533..d1eebf47 100644 | |
166 | --- a/src/os/unix/ngx_socket.h | |
167 | +++ b/src/os/unix/ngx_socket.h | |
168 | @@ -38,6 +38,17 @@ int ngx_blocking(ngx_socket_t s); | |
169 | ||
170 | #endif | |
171 | ||
172 | +#if (NGX_HAVE_FD_CLOEXEC) | |
173 | + | |
174 | +#define ngx_cloexec(s) fcntl(s, F_SETFD, FD_CLOEXEC) | |
175 | +#define ngx_cloexec_n "fcntl(FD_CLOEXEC)" | |
176 | + | |
177 | +/* at least FD_CLOEXEC is required to ensure connection fd is closed | |
178 | + * after execve */ | |
179 | +#define HAVE_SOCKET_CLOEXEC_PATCH 1 | |
180 | + | |
181 | +#endif | |
182 | + | |
183 | int ngx_tcp_nopush(ngx_socket_t s); | |
184 | int ngx_tcp_push(ngx_socket_t s); | |
185 |