comparison src/os/unix/ngx_process.c @ 218:05592fd7a436

nginx-0.0.1-2004-01-05-23:55:48 import
author Igor Sysoev <igor@sysoev.ru>
date Mon, 05 Jan 2004 20:55:48 +0000
parents 8dee38ea9117
children f57597ec5249
comparison
equal deleted inserted replaced
217:c5d1cdcb04ec 218:05592fd7a436
1 1
2 #include <ngx_config.h> 2 #include <ngx_config.h>
3 #include <ngx_core.h> 3 #include <ngx_core.h>
4 4
5 5
6 void testone(ngx_log_t *log) 6 static void ngx_exec_proc(ngx_cycle_t *cycle, void *data);
7 { 7
8 ngx_log_debug(log, "child process"); 8 ngx_uint_t ngx_last_process;
9 ngx_msleep(5000); 9 ngx_process_t ngx_processes[NGX_MAX_PROCESSES];
10 exit(0); 10
11 } 11
12 12 ngx_int_t ngx_spawn_process(ngx_cycle_t *cycle,
13 13 ngx_spawn_proc_pt proc, void *data,
14 int ngx_spawn_process(ngx_log_t *log) 14 char *name, ngx_int_t respawn)
15 { 15 {
16 pid_t pid; 16 sigset_t set, oset;
17 sigset_t set, oset; 17 ngx_pid_t pid;
18
19 if (respawn < 0) {
20 sigemptyset(&set);
21 sigaddset(&set, SIGCHLD);
22 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
23 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
24 "sigprocmask() failed while spawning %s", name);
25 return NGX_ERROR;
26 }
27 }
28
29 pid = fork();
30
31 if (pid == -1) {
32 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
33 "fork() failed while spawning \"%s\"", name);
34 }
35
36 if (pid == -1 || pid == 0) {
37 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
38 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
39 "sigprocmask() failed while spawning %s", name);
40 return NGX_ERROR;
41 }
42 }
43
44 switch (pid) {
45 case -1:
46 return NGX_ERROR;
47
48 case 0:
49 proc(cycle, data);
50 break;
51
52 default:
53 break;
54 }
55
56 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
57 "spawn %s: " PID_T_FMT, name, pid);
58
59 if (respawn >= 0) {
60 ngx_processes[respawn].pid = pid;
61 ngx_processes[respawn].exited = 0;
62 return NGX_OK;
63 }
64
65 ngx_processes[ngx_last_process].pid = pid;
66 ngx_processes[ngx_last_process].proc = proc;
67 ngx_processes[ngx_last_process].data = data;
68 ngx_processes[ngx_last_process].name = name;
69 ngx_processes[ngx_last_process].respawn =
70 (respawn == NGX_PROCESS_RESPAWN) ? 1 : 0;
71 ngx_processes[ngx_last_process].detached =
72 (respawn == NGX_PROCESS_DETACHED) ? 1 : 0;
73 ngx_processes[ngx_last_process].exited = 0;
74 ngx_processes[ngx_last_process].exiting = 0;
75 ngx_last_process++;
76
77 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
78 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
79 "sigprocmask() failed while spawning %s", name);
80 return NGX_ERROR;
81 }
82
83 return NGX_OK;
84 }
85
86
87 ngx_int_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
88 {
89 if (ngx_spawn_process(cycle, ngx_exec_proc, ctx, ctx->name,
90 NGX_PROCESS_DETACHED) == NGX_ERROR)
91 {
92 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
93 "can not spawn %s", ctx->name);
94 return NGX_ERROR;
95 }
96
97 return NGX_OK;
98 }
99
100
101 static void ngx_exec_proc(ngx_cycle_t *cycle, void *data)
102 {
103 ngx_exec_ctx_t *ctx = data;
104
105 if (execve(ctx->path, ctx->argv, ctx->envp) == -1) {
106 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
107 "execve() failed while executing %s \"%s\"",
108 ctx->name, ctx->path);
109 }
110
111 exit(1);
112 }
113
114
115 void ngx_signal_processes(ngx_cycle_t *cycle, ngx_int_t signal)
116 {
117 sigset_t set, oset;
118 ngx_uint_t i;
18 119
19 sigemptyset(&set); 120 sigemptyset(&set);
20 sigaddset(&set, SIGCHLD); 121 sigaddset(&set, SIGCHLD);
21 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) { 122 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
22 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); 123 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
23 } 124 "sigprocmask() failed while signaling processes");
24 125 return;
25 pid = fork(); 126 }
26 127
27 if (pid == -1 || pid == 0) { 128 for (i = 0; i < ngx_last_process; i++) {
28 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { 129
29 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, 130 if (ngx_processes[i].detached) {
30 "sigprocmask() failed"); 131 continue;
31 } 132 }
32 } 133
33 134 if (ngx_processes[i].exited) {
34 switch (pid) { 135 if (i != --ngx_last_process) {
35 case -1: 136 ngx_processes[i--] = ngx_processes[ngx_last_process];
36 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "fork() failed"); 137 }
37 return NGX_ERROR; 138 continue;
38 139 }
39 case 0: 140
40 testone(log); 141 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
41 break; 142 "kill (" PID_T_FMT ", %d)" ,
42 143 ngx_processes[i].pid, signal);
43 default: 144
44 break; 145 if (kill(ngx_processes[i].pid, signal) == -1) {
45 } 146 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
46 147 "kill(%d, %d) failed", ngx_processes[i].pid, signal);
47 ngx_log_debug(log, "parent process, child: " PID_T_FMT _ pid); 148 continue;
48 149 }
49 /* book keeping */ 150
151 if (signal != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
152 ngx_processes[i].exiting = 1;
153 }
154 }
50 155
51 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) { 156 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
52 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed"); 157 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
53 } 158 "sigprocmask() failed while signaling processes");
54 159 }
55 return NGX_OK; 160 }
56 } 161
57 162
58 163 void ngx_respawn_processes(ngx_cycle_t *cycle)
164 {
165 sigset_t set, oset;
166 ngx_uint_t i;
167
168 sigemptyset(&set);
169 sigaddset(&set, SIGCHLD);
170 if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
171 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
172 "sigprocmask() failed while respawning processes");
173 return;
174 }
175
176 /*
177 * to avoid a race condition we can check and set value of ngx_respawn
178 * only in signal handler or while SIGCHLD is blocked
179 */
180
181 if (ngx_respawn) {
182
183 for (i = 0; i < ngx_last_process; i++) {
184 if (!ngx_processes[i].exited) {
185 continue;
186 }
187
188 if (!ngx_processes[i].respawn) {
189 if (i != --ngx_last_process) {
190 ngx_processes[i--] = ngx_processes[ngx_last_process];
191 }
192 continue;
193 }
194
195 if (ngx_spawn_process(cycle,
196 ngx_processes[i].proc, ngx_processes[i].data,
197 ngx_processes[i].name, i) == NGX_ERROR)
198 {
199 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
200 "can not respawn %s", ngx_processes[i].name);
201 }
202 }
203
204 ngx_respawn = 0;
205 }
206
207 if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
208 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
209 "sigprocmask() failed while respawning processes");
210 }
211 }
212
213
214 #if 0
59 void ngx_sigchld_handler(int signo) 215 void ngx_sigchld_handler(int signo)
60 { 216 {
61 int status, one; 217 int status;
62 pid_t pid; 218 char *process;
63 ngx_err_t err; 219 ngx_pid_t pid;
64 struct timeval tv; 220 ngx_err_t err;
221 ngx_uint_t i, one;
222 struct timeval tv;
65 223
66 ngx_gettimeofday(&tv); 224 ngx_gettimeofday(&tv);
67 225 ngx_time_update(tv.tv_sec);
68 if (ngx_cached_time != tv.tv_sec) { 226
69 ngx_cached_time = tv.tv_sec; 227 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
70 ngx_time_update(); 228 "signal #%d (SIGCHLD) received", signo);
71 } 229 }
72 230 #endif
231
232
233 void ngx_process_get_status()
234 {
235 int status;
236 char *process;
237 ngx_pid_t pid;
238 ngx_err_t err;
239 ngx_uint_t i, one;
240 struct timeval tv;
73 one = 0; 241 one = 0;
74 242
75 for ( ;; ) { 243 for ( ;; ) {
76 pid = waitpid(-1, &status, WNOHANG); 244 pid = waitpid(-1, &status, WNOHANG);
77 245
94 "waitpid() failed"); 262 "waitpid() failed");
95 return; 263 return;
96 } 264 }
97 265
98 one = 1; 266 one = 1;
99 267 process = "";
100 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, 268
101 "process " PID_T_FMT " exited with code %d", pid, status); 269 for (i = 0; i < ngx_last_process; i++) {
102 270 if (ngx_processes[i].pid == pid) {
103 /* TODO: restart handler */ 271 ngx_processes[i].status = status;
104 272
105 #if 0 273 if (!ngx_processes[i].exiting) {
106 ngx_msleep(2000); 274 ngx_processes[i].exited = 1;
107 #endif 275
108 276 if (ngx_processes[i].respawn) {
109 #if 0 277 ngx_respawn = 1;
110 ngx_spawn_process(ngx_cycle->log); 278 }
111 #endif 279 }
112 } 280
113 } 281 process = ngx_processes[i].name;
282 break;
283 }
284 }
285
286 if (i == ngx_last_process) {
287 process = "unknown process";
288 }
289
290 if (WTERMSIG(status)) {
291 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
292 "%s " PID_T_FMT " exited on signal %d%s",
293 process, pid, WTERMSIG(status),
294 WCOREDUMP(status) ? " (core dumped)" : "");
295
296 } else {
297 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
298 "%s " PID_T_FMT " exited with code %d",
299 process, pid, WEXITSTATUS(status));
300 }
301 }
302 }