comparison src/os/unix/ngx_process.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children cc9f381affaa
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_channel.h>
11
12
13 static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
14
15 ngx_int_t ngx_process_slot;
16 ngx_socket_t ngx_channel;
17 ngx_int_t ngx_last_process;
18 ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
19
20
21 ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
22 ngx_spawn_proc_pt proc, void *data,
23 char *name, ngx_int_t respawn)
24 {
25 u_long on;
26 ngx_pid_t pid;
27 ngx_int_t s;
28
29 if (respawn >= 0) {
30 s = respawn;
31
32 } else {
33 for (s = 0; s < ngx_last_process; s++) {
34 if (ngx_processes[s].pid == -1) {
35 break;
36 }
37 }
38
39 if (s == NGX_MAX_PROCESSES) {
40 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
41 "no more than %d processes can be spawned",
42 NGX_MAX_PROCESSES);
43 return NGX_ERROR;
44 }
45 }
46
47
48 if (respawn != NGX_PROCESS_DETACHED) {
49
50 /* Solaris 9 still has no AF_LOCAL */
51
52 if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
53 {
54 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
55 "socketpair() failed while spawning \"%s\"", name);
56 return NGX_ERROR;
57 }
58
59 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
60 "channel %d:%d",
61 ngx_processes[s].channel[0],
62 ngx_processes[s].channel[1]);
63
64 if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
65 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
66 ngx_nonblocking_n " failed while spawning \"%s\"",
67 name);
68 ngx_close_channel(ngx_processes[s].channel, cycle->log);
69 return NGX_ERROR;
70 }
71
72 if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
73 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
74 ngx_nonblocking_n " failed while spawning \"%s\"",
75 name);
76 ngx_close_channel(ngx_processes[s].channel, cycle->log);
77 return NGX_ERROR;
78 }
79
80 on = 1;
81 if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
82 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
83 "ioctl(FIOASYNC) failed while spawning \"%s\"", name);
84 ngx_close_channel(ngx_processes[s].channel, cycle->log);
85 return NGX_ERROR;
86 }
87
88 if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
89 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
90 "fcntl(F_SETOWN) failed while spawning \"%s\"", name);
91 ngx_close_channel(ngx_processes[s].channel, cycle->log);
92 return NGX_ERROR;
93 }
94
95 if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
96 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
97 "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
98 name);
99 ngx_close_channel(ngx_processes[s].channel, cycle->log);
100 return NGX_ERROR;
101 }
102
103 if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
104 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
105 "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
106 name);
107 ngx_close_channel(ngx_processes[s].channel, cycle->log);
108 return NGX_ERROR;
109 }
110
111 ngx_channel = ngx_processes[s].channel[1];
112
113 } else {
114 ngx_processes[s].channel[0] = -1;
115 ngx_processes[s].channel[1] = -1;
116 }
117
118 ngx_process_slot = s;
119
120
121 pid = fork();
122
123 switch (pid) {
124
125 case -1:
126 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
127 "fork() failed while spawning \"%s\"", name);
128 ngx_close_channel(ngx_processes[s].channel, cycle->log);
129 return NGX_ERROR;
130
131 case 0:
132 ngx_pid = ngx_getpid();
133 proc(cycle, data);
134 break;
135
136 default:
137 break;
138 }
139
140 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
141 "spawn %s: " PID_T_FMT, name, pid);
142
143 ngx_processes[s].pid = pid;
144 ngx_processes[s].exited = 0;
145
146 if (respawn >= 0) {
147 return pid;
148 }
149
150 ngx_processes[s].proc = proc;
151 ngx_processes[s].data = data;
152 ngx_processes[s].name = name;
153 ngx_processes[s].exiting = 0;
154
155 switch (respawn) {
156
157 case NGX_PROCESS_RESPAWN:
158 ngx_processes[s].respawn = 1;
159 ngx_processes[s].just_respawn = 0;
160 ngx_processes[s].detached = 0;
161 break;
162
163 case NGX_PROCESS_JUST_RESPAWN:
164 ngx_processes[s].respawn = 1;
165 ngx_processes[s].just_respawn = 1;
166 ngx_processes[s].detached = 0;
167 break;
168
169 case NGX_PROCESS_DETACHED:
170 ngx_processes[s].respawn = 0;
171 ngx_processes[s].just_respawn = 0;
172 ngx_processes[s].detached = 1;
173 break;
174 }
175
176 if (s == ngx_last_process) {
177 ngx_last_process++;
178 }
179
180 return pid;
181 }
182
183
184 ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
185 {
186 return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name,
187 NGX_PROCESS_DETACHED);
188 }
189
190
191 static void ngx_execute_proc(ngx_cycle_t *cycle, void *data)
192 {
193 ngx_exec_ctx_t *ctx = data;
194
195 if (execve(ctx->path, ctx->argv, ctx->envp) == -1) {
196 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
197 "execve() failed while executing %s \"%s\"",
198 ctx->name, ctx->path);
199 }
200
201 exit(1);
202 }
203
204
205 void ngx_process_get_status()
206 {
207 int status;
208 char *process;
209 ngx_pid_t pid;
210 ngx_err_t err;
211 ngx_int_t i;
212 ngx_uint_t one;
213 struct timeval tv;
214 one = 0;
215
216 for ( ;; ) {
217 pid = waitpid(-1, &status, WNOHANG);
218
219 if (pid == 0) {
220 return;
221 }
222
223 if (pid == -1) {
224 err = ngx_errno;
225
226 if (err == NGX_EINTR) {
227 continue;
228 }
229
230 if (err == NGX_ECHILD && one) {
231 return;
232 }
233
234 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
235 "waitpid() failed");
236 return;
237 }
238
239
240 if (ngx_accept_mutex_ptr) {
241
242 /*
243 * unlock the accept mutex if the abnormally exited process
244 * held it
245 */
246
247 ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0);
248 }
249
250
251 one = 1;
252 process = "unknown process";
253
254 for (i = 0; i < ngx_last_process; i++) {
255 if (ngx_processes[i].pid == pid) {
256 ngx_processes[i].status = status;
257 ngx_processes[i].exited = 1;
258 process = ngx_processes[i].name;
259 break;
260 }
261 }
262
263 if (WTERMSIG(status)) {
264 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
265 "%s " PID_T_FMT " exited on signal %d%s",
266 process, pid, WTERMSIG(status),
267 WCOREDUMP(status) ? " (core dumped)" : "");
268
269 } else {
270 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
271 "%s " PID_T_FMT " exited with code %d",
272 process, pid, WEXITSTATUS(status));
273 }
274
275 if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
276 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
277 "%s " PID_T_FMT
278 " exited with fatal code %d and could not respawn",
279 process, pid, WEXITSTATUS(status));
280 ngx_processes[i].respawn = 0;
281 }
282 }
283 }