1 #include "uwsgi.h"
2 
3 extern struct uwsgi_server uwsgi;
4 
worker_wakeup()5 void worker_wakeup() {
6 }
7 
uwsgi_worker_exceptions(int wid)8 uint64_t uwsgi_worker_exceptions(int wid) {
9 	uint64_t total = 0;
10 	int i;
11 	for(i=0;i<uwsgi.cores;i++) {
12 		total += uwsgi.workers[wid].cores[i].exceptions;
13 	}
14 
15 	return total;
16 }
17 
uwsgi_curse(int wid,int sig)18 void uwsgi_curse(int wid, int sig) {
19 	uwsgi.workers[wid].cursed_at = uwsgi_now();
20         uwsgi.workers[wid].no_mercy_at = uwsgi.workers[wid].cursed_at + uwsgi.worker_reload_mercy;
21 
22 	if (sig) {
23 		(void) kill(uwsgi.workers[wid].pid, sig);
24 	}
25 }
26 
uwsgi_curse_mule(int mid,int sig)27 void uwsgi_curse_mule(int mid, int sig) {
28 	uwsgi.mules[mid].cursed_at = uwsgi_now();
29 	uwsgi.mules[mid].no_mercy_at = uwsgi.mules[mid].cursed_at + uwsgi.mule_reload_mercy;
30 
31 	if (sig) {
32 		(void) kill(uwsgi.mules[mid].pid, sig);
33 	}
34 }
35 
uwsgi_signal_spoolers(int signum)36 static void uwsgi_signal_spoolers(int signum) {
37 
38         struct uwsgi_spooler *uspool = uwsgi.spoolers;
39         while (uspool) {
40                 if (uspool->pid > 0) {
41                         kill(uspool->pid, signum);
42                         uwsgi_log("killing the spooler with pid %d\n", uspool->pid);
43                 }
44                 uspool = uspool->next;
45         }
46 
47 }
uwsgi_destroy_processes()48 void uwsgi_destroy_processes() {
49 
50 	int i;
51 	int waitpid_status;
52 
53         uwsgi_signal_spoolers(SIGKILL);
54 
55         uwsgi_detach_daemons();
56 
57         for (i = 0; i < ushared->gateways_cnt; i++) {
58                 if (ushared->gateways[i].pid > 0) {
59                         kill(ushared->gateways[i].pid, SIGKILL);
60 			waitpid(ushared->gateways[i].pid, &waitpid_status, 0);
61 			uwsgi_log("gateway \"%s %d\" has been buried (pid: %d)\n", ushared->gateways[i].name, ushared->gateways[i].num, (int) ushared->gateways[i].pid);
62 		}
63         }
64 
65 	if (uwsgi.emperor_pid > 0) {
66                 kill(uwsgi.emperor_pid, SIGINT);
67 		time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
68 		// increase timeout for being more tolerant
69 		timeout+=2;
70 		int waitpid_status;
71 		while (uwsgi_now() < timeout) {
72 			pid_t diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG);
73 			if (diedpid == uwsgi.emperor_pid) {
74 				goto nomoremperor;
75 			}
76 			uwsgi_log("waiting for Emperor death...\n");
77 			sleep(1);
78 		}
79 		kill(uwsgi.emperor_pid, SIGKILL);
80 		waitpid(uwsgi.emperor_pid, &waitpid_status, 0);
81 nomoremperor:
82 		uwsgi_log("The Emperor has been buried (pid: %d)\n", (int) uwsgi.emperor_pid);
83 	}
84 }
85 
86 
87 
uwsgi_master_cleanup_hooks(void)88 void uwsgi_master_cleanup_hooks(void) {
89 
90 	int j;
91 
92 	// could be an inherited atexit hook
93 	if (uwsgi.mypid != uwsgi.workers[0].pid)
94 		return;
95 
96 	uwsgi.status.is_cleaning = 1;
97 
98 	for (j = 0; j < uwsgi.gp_cnt; j++) {
99 		if (uwsgi.gp[j]->master_cleanup) {
100 			uwsgi.gp[j]->master_cleanup();
101 		}
102 	}
103 
104 	for (j = 0; j < 256; j++) {
105 		if (uwsgi.p[j]->master_cleanup) {
106 			uwsgi.p[j]->master_cleanup();
107 		}
108 	}
109 
110 }
111 
112 
uwsgi_calc_cheaper(void)113 int uwsgi_calc_cheaper(void) {
114 
115 	int i;
116 	static time_t last_check = 0;
117 	int check_interval = uwsgi.master_interval;
118 
119 	if (!last_check)
120 		last_check = uwsgi_now();
121 
122 	time_t now = uwsgi_now();
123 	if (!check_interval)
124 		check_interval = 1;
125 
126 	if ((now - last_check) < check_interval)
127 		return 1;
128 
129 	last_check = now;
130 
131 	int ignore_algo = 0;
132 	int needed_workers = 0;
133 
134 	// first check if memory usage is not exceeded
135 	if (uwsgi.cheaper_rss_limit_soft) {
136 		unsigned long long total_rss = 0;
137 		int i;
138 		int active_workers = 0;
139 		for(i=1;i<=uwsgi.numproc;i++) {
140 			if (!uwsgi.workers[i].cheaped) {
141 				total_rss += uwsgi.workers[i].rss_size;
142 				active_workers++;
143 			}
144 		}
145 		if (uwsgi.cheaper_rss_limit_hard && active_workers > 1 && total_rss >= uwsgi.cheaper_rss_limit_hard) {
146 			uwsgi_log("cheaper hard rss memory limit exceeded, cheap one of %d workers\n", active_workers);
147 			needed_workers = -1;
148 			ignore_algo = 1;
149 		}
150 		else if (total_rss >= uwsgi.cheaper_rss_limit_soft) {
151 #ifdef UWSGI_DEBUG
152 			uwsgi_log("cheaper soft rss memory limit exceeded, can't spawn more workers\n");
153 #endif
154 			ignore_algo = 1;
155 		}
156 	}
157 
158 	// then check for fifo
159 	if (uwsgi.cheaper_fifo_delta != 0) {
160 		if (!ignore_algo) {
161 			needed_workers = uwsgi.cheaper_fifo_delta;
162 			ignore_algo = 1;
163 		}
164 		uwsgi.cheaper_fifo_delta = 0;
165 		goto safe;
166 	}
167 
168 	// if cheaper limits wants to change worker count, then skip cheaper algo
169 	if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
170 	// safe check to verify if cheaper algo obeyed ignore_algo value
171 	if (ignore_algo && needed_workers > 0) {
172 		uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
173 		needed_workers = 0;
174 	}
175 
176 safe:
177 	if (needed_workers > 0) {
178 		for (i = 1; i <= uwsgi.numproc; i++) {
179 			if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
180 				if (uwsgi_respawn_worker(i)) {
181 					uwsgi.cheaper_fifo_delta += needed_workers;
182 					return 0;
183 				}
184 				needed_workers--;
185 			}
186 			if (needed_workers == 0)
187 				break;
188 		}
189 	}
190 	else if (needed_workers < 0) {
191 		while (needed_workers < 0) {
192 			int oldest_worker = 0;
193 			time_t oldest_worker_spawn = INT_MAX;
194 			for (i = 1; i <= uwsgi.numproc; i++) {
195 				if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
196 					if (uwsgi_worker_is_busy(i) == 0) {
197 						if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
198 							oldest_worker_spawn = uwsgi.workers[i].last_spawn;
199 							oldest_worker = i;
200 						}
201 					}
202 				}
203 			}
204 			if (oldest_worker > 0) {
205 #ifdef UWSGI_DEBUG
206 				uwsgi_log("worker %d should die...\n", oldest_worker);
207 #endif
208 				uwsgi.workers[oldest_worker].cheaped = 1;
209 				uwsgi.workers[oldest_worker].rss_size = 0;
210 				uwsgi.workers[oldest_worker].vsz_size = 0;
211 				uwsgi.workers[oldest_worker].manage_next_request = 0;
212 				uwsgi_curse(oldest_worker, SIGWINCH);
213 			}
214 			else {
215 				// Return it to the pool
216 				uwsgi.cheaper_fifo_delta--;
217 			}
218 			needed_workers++;
219 		}
220 	}
221 
222 	return 1;
223 }
224 
225 // fake algo to allow control with the fifo
uwsgi_cheaper_algo_manual(int can_spawn)226 int uwsgi_cheaper_algo_manual(int can_spawn) {
227 	return 0;
228 }
229 
230 /*
231 
232         -- Cheaper, spare algorithm, adapted from old-fashioned spare system --
233 
234         when all of the workers are busy, the overload_count is incremented.
235         as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
236         at most cheaper_step (default to 1) new workers are spawned.
237 
238         when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
239         If overload_count reaches 0, the system will count active workers (the ones uncheaped) and busy workers (the ones running a request)
240 	if there is exacly 1 free worker we are in "stable state" (1 spare worker available). no worker will be touched.
241 	if the number of active workers is higher than uwsgi.cheaper_count and at least uwsgi.cheaper_overload cycles are passed from the last
242         "cheap it" procedure, then cheap a worker.
243 
244         Example:
245             10 processes
246             2 cheaper
247             2 cheaper step
248             3 cheaper_overload
249             1 second master cycle
250 
251             there are 7 workers running (triggered by some kind of spike activity).
252 	    Of this, 6 are busy, 1 is free. We are in stable state.
253             After a bit the spike disappear and idle_count start to increase.
254 
255 	    After 3 seconds (uwsgi.cheaper_overload cycles) the oldest worker will be cheaped. This will happens
256 	    every  seconds (uwsgi.cheaper_overload cycles) til the number of workers is == uwsgi.cheaper_count.
257 
258 	    If during the "cheap them all" procedure, an overload condition come again (another spike) the "cheap them all"
259             will be interrupted.
260 
261 
262 */
263 
264 
uwsgi_cheaper_algo_spare(int can_spawn)265 int uwsgi_cheaper_algo_spare(int can_spawn) {
266 
267 	int i;
268 	static uint64_t overload_count = 0;
269 	static uint64_t idle_count = 0;
270 
271 	// step 1 -> count the number of busy workers
272 	for (i = 1; i <= uwsgi.numproc; i++) {
273 		if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
274 			// if a non-busy worker is found, the overload_count is decremented and stop the cycle
275 			if (uwsgi_worker_is_busy(i) == 0) {
276 				if (overload_count > 0)
277 					overload_count--;
278 				goto healthy;
279 			}
280 		}
281 	}
282 
283 	overload_count++;
284 	idle_count = 0;
285 
286 healthy:
287 
288 	// are we overloaded ?
289 	if (can_spawn && overload_count > uwsgi.cheaper_overload) {
290 
291 #ifdef UWSGI_DEBUG
292 		uwsgi_log("overloaded !!!\n");
293 #endif
294 
295 		// activate the first available worker (taking step into account)
296 		int decheaped = 0;
297 		// search for cheaped workers
298 		for (i = 1; i <= uwsgi.numproc; i++) {
299 			if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
300 				decheaped++;
301 				if (decheaped >= uwsgi.cheaper_step)
302 					break;
303 			}
304 		}
305 		// reset overload
306 		overload_count = 0;
307 		// return the maximum number of workers to spawn
308 		return decheaped;
309 	}
310 	// we are no more overloaded
311 	else if (overload_count == 0) {
312 		// how many active workers ?
313 		int active_workers = 0;
314 		int busy_workers = 0;
315 		for (i = 1; i <= uwsgi.numproc; i++) {
316 			if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
317 				active_workers++;
318 				if (uwsgi_worker_is_busy(i) == 1)
319 					busy_workers++;
320 			}
321 		}
322 
323 #ifdef UWSGI_DEBUG
324 		uwsgi_log("active workers %d busy_workers %d\n", active_workers, busy_workers);
325 #endif
326 
327 		// special condition: uwsgi.cheaper running workers and 1 free
328 		if (active_workers > busy_workers && active_workers - busy_workers == 1) {
329 #ifdef UWSGI_DEBUG
330 			uwsgi_log("stable status: 1 spare worker\n");
331 #endif
332 			return 0;
333 		}
334 
335 		idle_count++;
336 
337 		if (active_workers > uwsgi.cheaper_count && idle_count % uwsgi.cheaper_overload == 0) {
338 			// we are in "cheap them all"
339 			return -1;
340 		}
341 	}
342 
343 	return 0;
344 
345 }
346 
347 
348 /*
349 
350 	-- Cheaper,  backlog algorithm (supported only on Linux) --
351 
352         increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
353 	Decrese when lower.
354 
355 */
356 
uwsgi_cheaper_algo_backlog(int can_spawn)357 int uwsgi_cheaper_algo_backlog(int can_spawn) {
358 
359 	int i;
360 #ifdef __linux__
361 	int backlog = uwsgi.shared->backlog;
362 #else
363 	int backlog = 0;
364 #endif
365 
366 	if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
367 		// activate the first available worker (taking step into account)
368 		int decheaped = 0;
369 		// search for cheaped workers
370 		for (i = 1; i <= uwsgi.numproc; i++) {
371 			if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
372 				decheaped++;
373 				if (decheaped >= uwsgi.cheaper_step)
374 					break;
375 			}
376 		}
377 		// return the maximum number of workers to spawn
378 		return decheaped;
379 
380 	}
381 	else if (backlog < (int) uwsgi.cheaper_overload) {
382 		int active_workers = 0;
383 		for (i = 1; i <= uwsgi.numproc; i++) {
384 			if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
385 				active_workers++;
386 			}
387 		}
388 
389 		if (active_workers > uwsgi.cheaper_count) {
390 			return -1;
391 		}
392 	}
393 
394 	return 0;
395 }
396 
397 
398 // reload uWSGI, close unneded file descriptor, restore the original environment and re-exec the binary
399 
uwsgi_reload(char ** argv)400 void uwsgi_reload(char **argv) {
401 	int i;
402 	int waitpid_status;
403 
404 	// hack for removing garbage generated by embedded loaders (like pyuwsgi)
405 	if (uwsgi.new_argc) {
406 		char **tmp_argv = argv;
407 		for(;;) {
408 			char *arg = *tmp_argv;
409 			if (!arg)
410 				break;
411 			if (strlen(arg) == 0)
412 			{
413 				*tmp_argv = NULL;
414 			}
415 			tmp_argv++;
416 		}
417 	}
418 
419 	if (!uwsgi.master_is_reforked) {
420 
421 		// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
422 		for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
423 			waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
424 		}
425 
426 		// call master cleanup hooks
427 		uwsgi_master_cleanup_hooks();
428 
429 		if (uwsgi.exit_on_reload) {
430 			uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
431 			exit(0);
432 		}
433 
434 		// call atexit user exec
435 		uwsgi_exec_atexit();
436 
437 		uwsgi_log("binary reloading uWSGI...\n");
438 	}
439 	else {
440 		uwsgi_log("fork()'ing uWSGI...\n");
441 	}
442 
443 	// ask for configuration (if needed)
444 	if (uwsgi.has_emperor && uwsgi.emperor_fd_config > -1) {
445 		char byte = 2;
446                 if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
447                         uwsgi_error("uwsgi_reload()/write()");
448                 }
449 	}
450 
451 	uwsgi_log("chdir() to %s\n", uwsgi.cwd);
452 	if (chdir(uwsgi.cwd)) {
453 		uwsgi_error("uwsgi_reload()/chdir()");
454 	}
455 
456 	/* check fd table (a module can obviosly open some fd on initialization...) */
457 	uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
458 	for (i = 3; i < (int) uwsgi.max_fd; i++) {
459 		if (uwsgi.close_on_exec2) fcntl(i, F_SETFD, 0);
460 
461 		if (uwsgi_fd_is_safe(i)) continue;
462 
463 		int found = 0;
464 
465 		struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
466 		while (uwsgi_sock) {
467 			if (i == uwsgi_sock->fd) {
468 				uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
469 				found = 1;
470 				break;
471 			}
472 			uwsgi_sock = uwsgi_sock->next;
473 		}
474 
475 		uwsgi_sock = uwsgi.shared_sockets;
476 		while (uwsgi_sock) {
477 			if (i == uwsgi_sock->fd) {
478 				uwsgi_log("found fd %d mapped to shared socket %d (%s)\n", i, uwsgi_get_shared_socket_num(uwsgi_sock), uwsgi_sock->name);
479 				found = 1;
480 				break;
481 			}
482 			uwsgi_sock = uwsgi_sock->next;
483 		}
484 
485 		if (found) continue;
486 
487 		if (uwsgi.has_emperor) {
488 			if (i == uwsgi.emperor_fd) {
489 				continue;
490 			}
491 
492 			if (i == uwsgi.emperor_fd_config) {
493 				continue;
494 			}
495 		}
496 
497 		if (uwsgi.alarm_thread) {
498 			if (i == uwsgi.alarm_thread->queue) continue;
499 			if (i == uwsgi.alarm_thread->pipe[0]) continue;
500 			if (i == uwsgi.alarm_thread->pipe[1]) continue;
501 		}
502 
503 		if (uwsgi.log_master) {
504 			if (uwsgi.original_log_fd > -1) {
505 				if (i == uwsgi.original_log_fd) {
506 					continue;
507 				}
508 			}
509 
510 			if (uwsgi.shared->worker_log_pipe[0] > -1) {
511 				if (i == uwsgi.shared->worker_log_pipe[0]) {
512 					continue;
513 				}
514 			}
515 
516 			if (uwsgi.shared->worker_log_pipe[1] > -1) {
517 				if (i == uwsgi.shared->worker_log_pipe[1]) {
518 					continue;
519 				}
520 			}
521 
522 		}
523 
524 #ifdef __APPLE__
525 		fcntl(i, F_SETFD, FD_CLOEXEC);
526 #else
527 		close(i);
528 #endif
529 	}
530 
531 #ifndef UWSGI_IPCSEM_ATEXIT
532 	// free ipc semaphores if in use
533 	if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
534 		uwsgi_ipcsem_clear();
535 	}
536 #endif
537 
538 	uwsgi_log("running %s\n", uwsgi.binary_path);
539 	uwsgi_flush_logs();
540 	argv[0] = uwsgi.binary_path;
541 	//strcpy (argv[0], uwsgi.binary_path);
542 	if (uwsgi.log_master) {
543 		if (uwsgi.original_log_fd > -1) {
544 			dup2(uwsgi.original_log_fd, 1);
545 			dup2(1, 2);
546 		}
547 		if (uwsgi.shared->worker_log_pipe[0] > -1) {
548 			close(uwsgi.shared->worker_log_pipe[0]);
549 		}
550 		if (uwsgi.shared->worker_log_pipe[1] > -1) {
551 			close(uwsgi.shared->worker_log_pipe[1]);
552 		}
553 	}
554 	execvp(uwsgi.binary_path, argv);
555 	uwsgi_error("execvp()");
556 	// never here
557 	exit(1);
558 
559 }
560 
uwsgi_fixup_fds(int wid,int muleid,struct uwsgi_gateway * ug)561 void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
562 
563 	int i;
564 
565 	if (uwsgi.master_process) {
566 		if (uwsgi.master_queue > -1)
567 			close(uwsgi.master_queue);
568 		// close gateways
569 		if (!ug) {
570 			for (i = 0; i < ushared->gateways_cnt; i++) {
571 				close(ushared->gateways[i].internal_subscription_pipe[0]);
572 				close(ushared->gateways[i].internal_subscription_pipe[1]);
573 			}
574 		}
575 		struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
576 		while (ugs) {
577 			if (ug && !strcmp(ug->name, ugs->owner)) {
578 				ugs = ugs->next;
579 				continue;
580 			}
581 			// do not close shared sockets !!!
582 			if (!ugs->shared) {
583 				close(ugs->fd);
584 			}
585 			ugs = ugs->next;
586 		}
587 		// fix the communication pipe
588 		close(uwsgi.shared->worker_signal_pipe[0]);
589 		for (i = 1; i <= uwsgi.numproc; i++) {
590 			if (uwsgi.workers[i].signal_pipe[0] != -1)
591 				close(uwsgi.workers[i].signal_pipe[0]);
592 			if (i != wid) {
593 				if (uwsgi.workers[i].signal_pipe[1] != -1)
594 					close(uwsgi.workers[i].signal_pipe[1]);
595 			}
596 		}
597 
598 
599 		if (uwsgi.shared->spooler_signal_pipe[0] != -1)
600                 	close(uwsgi.shared->spooler_signal_pipe[0]);
601 		if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
602 			if (uwsgi.shared->spooler_signal_pipe[1] != -1)
603 				close(uwsgi.shared->spooler_signal_pipe[1]);
604 		}
605 
606 		if (uwsgi.shared->mule_signal_pipe[0] != -1)
607 			close(uwsgi.shared->mule_signal_pipe[0]);
608 
609 		if (muleid == 0) {
610 			if (uwsgi.shared->mule_signal_pipe[1] != -1)
611 				close(uwsgi.shared->mule_signal_pipe[1]);
612 			if (uwsgi.shared->mule_queue_pipe[1] != -1)
613 				close(uwsgi.shared->mule_queue_pipe[1]);
614 		}
615 
616 		for (i = 0; i < uwsgi.mules_cnt; i++) {
617 			if (uwsgi.mules[i].signal_pipe[0] != -1)
618 				close(uwsgi.mules[i].signal_pipe[0]);
619 			if (muleid != i + 1) {
620 				if (uwsgi.mules[i].signal_pipe[1] != -1)
621 					close(uwsgi.mules[i].signal_pipe[1]);
622 				if (uwsgi.mules[i].queue_pipe[1] != -1)
623 					close(uwsgi.mules[i].queue_pipe[1]);
624 			}
625 		}
626 
627 		for (i = 0; i < uwsgi.farms_cnt; i++) {
628 			if (uwsgi.farms[i].signal_pipe[0] != -1)
629 				close(uwsgi.farms[i].signal_pipe[0]);
630 
631 			if (muleid == 0) {
632 				if (uwsgi.farms[i].signal_pipe[1] != -1)
633 					close(uwsgi.farms[i].signal_pipe[1]);
634 				if (uwsgi.farms[i].queue_pipe[1] != -1)
635 					close(uwsgi.farms[i].queue_pipe[1]);
636 			}
637 		}
638 
639 		if (uwsgi.master_fifo_fd > -1) close(uwsgi.master_fifo_fd);
640 
641 		if (uwsgi.notify_socket_fd > -1) close(uwsgi.notify_socket_fd);
642 
643 #ifdef __linux__
644 		for(i=0;i<uwsgi.setns_fds_count;i++) {
645 			close(uwsgi.setns_fds[i]);
646 		}
647 #endif
648 
649 		// fd alarms
650 		struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
651         	while(uafd) {
652 			close(uafd->fd);
653                 	uafd = uafd->next;
654         	}
655 	}
656 
657 
658 }
659 
uwsgi_respawn_worker(int wid)660 int uwsgi_respawn_worker(int wid) {
661 
662 	int respawns = uwsgi.workers[wid].respawn_count;
663 	// the workers is not accepting (obviously)
664 	uwsgi.workers[wid].accepting = 0;
665 	// we count the respawns before errors...
666 	uwsgi.workers[wid].respawn_count++;
667 	// ... same for update time
668 	uwsgi.workers[wid].last_spawn = uwsgi.current_time;
669 	// ... and memory/harakiri
670 	uwsgi.workers[wid].harakiri = 0;
671 	uwsgi.workers[wid].user_harakiri = 0;
672 	uwsgi.workers[wid].pending_harakiri = 0;
673 	uwsgi.workers[wid].rss_size = 0;
674 	uwsgi.workers[wid].vsz_size = 0;
675 	// ... reset stopped_at
676 	uwsgi.workers[wid].cursed_at = 0;
677 	uwsgi.workers[wid].no_mercy_at = 0;
678 
679 	// internal statuses should be reset too
680 
681 	uwsgi.workers[wid].cheaped = 0;
682 	// SUSPENSION is managed by the user, not the master...
683 	//uwsgi.workers[wid].suspended = 0;
684 	uwsgi.workers[wid].sig = 0;
685 
686 	// this is required for various checks
687 	uwsgi.workers[wid].delta_requests = 0;
688 
689 	int i;
690 
691 	if (uwsgi.threaded_logger) {
692 		pthread_mutex_lock(&uwsgi.threaded_logger_lock);
693 	}
694 
695 	pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
696 
697 	if (pid == 0) {
698 		signal(SIGWINCH, worker_wakeup);
699 		signal(SIGTSTP, worker_wakeup);
700 		uwsgi.mywid = wid;
701 		uwsgi.mypid = getpid();
702 		// pid is updated by the master
703 		//uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
704 		// OVERENGINEERING (just to be safe)
705 		uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
706 		/*
707 		   uwsgi.workers[uwsgi.mywid].harakiri = 0;
708 		   uwsgi.workers[uwsgi.mywid].user_harakiri = 0;
709 		   uwsgi.workers[uwsgi.mywid].rss_size = 0;
710 		   uwsgi.workers[uwsgi.mywid].vsz_size = 0;
711 		 */
712 		// do not reset worker counters on reload !!!
713 		//uwsgi.workers[uwsgi.mywid].requests = 0;
714 		// ...but maintain a delta counter (yes this is racy in multithread)
715 		//uwsgi.workers[uwsgi.mywid].delta_requests = 0;
716 		//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
717 		//uwsgi.workers[uwsgi.mywid].respawn_count++;
718 		//uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
719 		uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
720 		/*
721 		   uwsgi.workers[uwsgi.mywid].cheaped = 0;
722 		   uwsgi.workers[uwsgi.mywid].suspended = 0;
723 		   uwsgi.workers[uwsgi.mywid].sig = 0;
724 		 */
725 
726 		// reset the apps count with a copy from the master
727 		uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
728 
729 		// reset wsgi_request structures
730 		for(i=0;i<uwsgi.cores;i++) {
731 			uwsgi.workers[uwsgi.mywid].cores[i].in_request = 0;
732 			memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
733 			memset(uwsgi.workers[uwsgi.mywid].cores[i].buffer, 0, sizeof(struct uwsgi_header));
734 		}
735 
736 		uwsgi_fixup_fds(wid, 0, NULL);
737 
738 		uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
739 
740 		if (uwsgi.master_process) {
741 			if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.status.is_cheap)) {
742 				for (i = 0; i < 256; i++) {
743 					if (uwsgi.p[i]->master_fixup) {
744 						uwsgi.p[i]->master_fixup(1);
745 					}
746 				}
747 			}
748 		}
749 
750 		return 1;
751 	}
752 	else if (pid < 1) {
753 		uwsgi_error("fork()");
754 	}
755 	else {
756 		// the pid is set only in the master, as the worker should never use it
757 		uwsgi.workers[wid].pid = pid;
758 
759 		if (respawns > 0) {
760 			uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
761 		}
762 		else {
763 			uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
764 		}
765 	}
766 
767 	if (uwsgi.threaded_logger) {
768 		pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
769 	}
770 
771 
772 	return 0;
773 }
774 
uwsgi_master_generate_stats()775 struct uwsgi_stats *uwsgi_master_generate_stats() {
776 
777 	int i;
778 
779 	struct uwsgi_stats *us = uwsgi_stats_new(8192);
780 
781 	if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION))
782 		goto end;
783 
784 #ifdef __linux__
785 	if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->backlog))
786 		goto end;
787 	if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->backlog_errors))
788 		goto end;
789 #endif
790 
791 	int signal_queue = 0;
792 	if (ioctl(uwsgi.shared->worker_signal_pipe[1], FIONREAD, &signal_queue)) {
793 		uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
794 	}
795 
796 	if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
797 		goto end;
798 
799 	if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) uwsgi.shared->load))
800 		goto end;
801 	if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) getpid()))
802 		goto end;
803 	if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) getuid()))
804 		goto end;
805 	if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) getgid()))
806 		goto end;
807 
808 	char *cwd = uwsgi_get_cwd();
809 	if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) {
810 		free(cwd);
811 		goto end;
812 	}
813 	free(cwd);
814 
815 	if (uwsgi.daemons) {
816 		if (uwsgi_stats_key(us, "daemons"))
817 			goto end;
818 		if (uwsgi_stats_list_open(us))
819 			goto end;
820 
821 		struct uwsgi_daemon *ud = uwsgi.daemons;
822 		while (ud) {
823 			if (uwsgi_stats_object_open(us))
824 				goto end;
825 
826 			// allocate 2x the size of original command
827 			// in case we need to escape all chars
828 			char *cmd = uwsgi_malloc((strlen(ud->command)*2)+1);
829 			escape_json(ud->command, strlen(ud->command), cmd);
830 			if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
831 				free(cmd);
832 				goto end;
833 			}
834 			free(cmd);
835 
836 			if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
837 				goto end;
838 			if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
839 				goto end;
840 			if (uwsgi_stats_object_close(us))
841 				goto end;
842 			if (ud->next) {
843 				if (uwsgi_stats_comma(us))
844 					goto end;
845 			}
846 			ud = ud->next;
847 		}
848 		if (uwsgi_stats_list_close(us))
849 			goto end;
850 		if (uwsgi_stats_comma(us))
851 			goto end;
852 	}
853 
854 	if (uwsgi_stats_key(us, "locks"))
855 		goto end;
856 	if (uwsgi_stats_list_open(us))
857 		goto end;
858 
859 	struct uwsgi_lock_item *uli = uwsgi.registered_locks;
860 	while (uli) {
861 		if (uwsgi_stats_object_open(us))
862 			goto end;
863 		if (uwsgi_stats_keylong(us, uli->id, (unsigned long long) uli->pid))
864 			goto end;
865 		if (uwsgi_stats_object_close(us))
866 			goto end;
867 		if (uli->next) {
868 			if (uwsgi_stats_comma(us))
869 				goto end;
870 		}
871 		uli = uli->next;
872 	}
873 
874 	if (uwsgi_stats_list_close(us))
875 		goto end;
876 	if (uwsgi_stats_comma(us))
877 		goto end;
878 
879 	if (uwsgi.caches) {
880 
881 
882 		if (uwsgi_stats_key(us, "caches"))
883                 goto end;
884 
885 		if (uwsgi_stats_list_open(us)) goto end;
886 
887 		struct uwsgi_cache *uc = uwsgi.caches;
888 		while(uc) {
889 			if (uwsgi_stats_object_open(us))
890                         	goto end;
891 
892 			if (uwsgi_stats_keyval_comma(us, "name", uc->name ? uc->name : "default"))
893                         	goto end;
894 
895 			if (uwsgi_stats_keyval_comma(us, "hash", uc->hash->name))
896                         	goto end;
897 
898 			if (uwsgi_stats_keylong_comma(us, "hashsize", (unsigned long long) uc->hashsize))
899 				goto end;
900 
901 			if (uwsgi_stats_keylong_comma(us, "keysize", (unsigned long long) uc->keysize))
902 				goto end;
903 
904 			if (uwsgi_stats_keylong_comma(us, "max_items", (unsigned long long) uc->max_items))
905 				goto end;
906 
907 			if (uwsgi_stats_keylong_comma(us, "blocks", (unsigned long long) uc->blocks))
908 				goto end;
909 
910 			if (uwsgi_stats_keylong_comma(us, "blocksize", (unsigned long long) uc->blocksize))
911 				goto end;
912 
913 			if (uwsgi_stats_keylong_comma(us, "items", (unsigned long long) uc->n_items))
914 				goto end;
915 
916 			if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) uc->hits))
917 				goto end;
918 
919 			if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
920 				goto end;
921 
922 			if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
923 				goto end;
924 
925 			if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
926 				goto end;
927 
928 			if (uwsgi_stats_object_close(us))
929 				goto end;
930 
931 			if (uc->next) {
932 				if (uwsgi_stats_comma(us))
933 					goto end;
934 			}
935 			uc = uc->next;
936 		}
937 
938 		if (uwsgi_stats_list_close(us))
939 		goto end;
940 
941 		if (uwsgi_stats_comma(us))
942 		goto end;
943 	}
944 
945 	if (uwsgi.has_metrics && !uwsgi.stats_no_metrics) {
946 		if (uwsgi_stats_key(us, "metrics"))
947                 	goto end;
948 
949 		if (uwsgi_stats_object_open(us))
950 			goto end;
951 
952 		uwsgi_rlock(uwsgi.metrics_lock);
953 		struct uwsgi_metric *um = uwsgi.metrics;
954 		while(um) {
955         		int64_t um_val = *um->value;
956 
957 			if (uwsgi_stats_key(us, um->name)) {
958 				uwsgi_rwunlock(uwsgi.metrics_lock);
959                 		goto end;
960 			}
961 
962 			if (uwsgi_stats_object_open(us)) {
963 				uwsgi_rwunlock(uwsgi.metrics_lock);
964                                 goto end;
965 			}
966 
967 			if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
968         			uwsgi_rwunlock(uwsgi.metrics_lock);
969 				goto end;
970 			}
971 
972 			if (uwsgi_stats_comma(us)) {
973         			uwsgi_rwunlock(uwsgi.metrics_lock);
974 				goto end;
975 			}
976 
977 			if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
978                                 uwsgi_rwunlock(uwsgi.metrics_lock);
979                                 goto end;
980                         }
981 
982 			if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
983         			uwsgi_rwunlock(uwsgi.metrics_lock);
984 				goto end;
985 			}
986 
987 			if (uwsgi_stats_object_close(us)) {
988                                 uwsgi_rwunlock(uwsgi.metrics_lock);
989                                 goto end;
990                         }
991 
992 			um = um->next;
993 			if (um) {
994 				if (uwsgi_stats_comma(us)) {
995         				uwsgi_rwunlock(uwsgi.metrics_lock);
996 					goto end;
997 				}
998 			}
999 		}
1000         	uwsgi_rwunlock(uwsgi.metrics_lock);
1001 
1002 		if (uwsgi_stats_object_close(us))
1003 			goto end;
1004 
1005 		if (uwsgi_stats_comma(us))
1006 		goto end;
1007 	}
1008 
1009 	if (uwsgi_stats_key(us, "sockets"))
1010 		goto end;
1011 
1012 	if (uwsgi_stats_list_open(us))
1013 		goto end;
1014 
1015 	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
1016 	while (uwsgi_sock) {
1017 		if (uwsgi_stats_object_open(us))
1018 			goto end;
1019 
1020 		if (uwsgi_stats_keyval_comma(us, "name", uwsgi_sock->name))
1021 			goto end;
1022 
1023 		if (uwsgi_stats_keyval_comma(us, "proto", uwsgi_sock->proto_name ? uwsgi_sock->proto_name : "uwsgi"))
1024 			goto end;
1025 
1026 		if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue))
1027 			goto end;
1028 
1029 		if (uwsgi_stats_keylong_comma(us, "max_queue", (unsigned long long) uwsgi_sock->max_queue))
1030 			goto end;
1031 
1032 		if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared))
1033 			goto end;
1034 
1035 		if (uwsgi_stats_keylong(us, "can_offload", (unsigned long long) uwsgi_sock->can_offload))
1036 			goto end;
1037 
1038 		if (uwsgi_stats_object_close(us))
1039 			goto end;
1040 
1041 		uwsgi_sock = uwsgi_sock->next;
1042 		if (uwsgi_sock) {
1043 			if (uwsgi_stats_comma(us))
1044 				goto end;
1045 		}
1046 	}
1047 
1048 	if (uwsgi_stats_list_close(us))
1049 		goto end;
1050 
1051 	if (uwsgi_stats_comma(us))
1052 		goto end;
1053 
1054 	if (uwsgi_stats_key(us, "workers"))
1055 		goto end;
1056 	if (uwsgi_stats_list_open(us))
1057 		goto end;
1058 
1059 	for (i = 0; i < uwsgi.numproc; i++) {
1060 		if (uwsgi_stats_object_open(us))
1061 			goto end;
1062 
1063 		if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id))
1064 			goto end;
1065 		if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
1066 			goto end;
1067 		if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
1068 			goto end;
1069 		if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
1070 			goto end;
1071 		if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
1072 			goto end;
1073 		if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi_worker_exceptions(i + 1)))
1074 			goto end;
1075 		if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
1076 			goto end;
1077 		if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals))
1078 			goto end;
1079 
1080 		if (ioctl(uwsgi.workers[i + 1].signal_pipe[1], FIONREAD, &signal_queue)) {
1081 			uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n");
1082 		}
1083 
1084 		if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue))
1085 			goto end;
1086 
1087 		if (uwsgi.workers[i + 1].cheaped) {
1088 			if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
1089 				goto end;
1090 		}
1091 		else if (uwsgi.workers[i + 1].suspended && !uwsgi_worker_is_busy(i+1)) {
1092 			if (uwsgi_stats_keyval_comma(us, "status", "pause"))
1093 				goto end;
1094 		}
1095 		else {
1096 			if (uwsgi.workers[i + 1].sig) {
1097 				if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
1098 					goto end;
1099 			}
1100 			else if (uwsgi_worker_is_busy(i+1)) {
1101 				if (uwsgi_stats_keyval_comma(us, "status", "busy"))
1102 					goto end;
1103 			}
1104 			else {
1105 				if (uwsgi_stats_keyval_comma(us, "status", "idle"))
1106 					goto end;
1107 			}
1108 		}
1109 
1110 		if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size))
1111 			goto end;
1112 		if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size))
1113 			goto end;
1114 
1115 		if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time))
1116 			goto end;
1117 		if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn))
1118 			goto end;
1119 		if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count))
1120 			goto end;
1121 
1122 		if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx))
1123 			goto end;
1124 		if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time))
1125 			goto end;
1126 
1127 		// applications list
1128 		if (uwsgi_stats_key(us, "apps"))
1129 			goto end;
1130 		if (uwsgi_stats_list_open(us))
1131 			goto end;
1132 
1133 		int j;
1134 
1135 		for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
1136 			struct uwsgi_app *ua = &uwsgi.workers[i + 1].apps[j];
1137 
1138 			if (uwsgi_stats_object_open(us))
1139 				goto end;
1140 			if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
1141 				goto end;
1142 			if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1))
1143 				goto end;
1144 
1145 			if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len))
1146 				goto end;
1147 			if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time))
1148 				goto end;
1149 
1150 			if (uwsgi_stats_keylong_comma(us, "requests", ua->requests))
1151 				goto end;
1152 			if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions))
1153 				goto end;
1154 
1155 			if (*ua->chdir) {
1156 				if (uwsgi_stats_keyval(us, "chdir", ua->chdir))
1157 					goto end;
1158 			}
1159 			else {
1160 				if (uwsgi_stats_keyval(us, "chdir", ""))
1161 					goto end;
1162 			}
1163 
1164 			if (uwsgi_stats_object_close(us))
1165 				goto end;
1166 
1167 			if (j < uwsgi.workers[i + 1].apps_cnt - 1) {
1168 				if (uwsgi_stats_comma(us))
1169 					goto end;
1170 			}
1171 		}
1172 
1173 
1174 		if (uwsgi_stats_list_close(us))
1175 			goto end;
1176 
1177 		if (uwsgi.stats_no_cores) goto nocores;
1178 
1179 		if (uwsgi_stats_comma(us))
1180 			goto end;
1181 
1182 		// cores list
1183 		if (uwsgi_stats_key(us, "cores"))
1184 			goto end;
1185 		if (uwsgi_stats_list_open(us))
1186 			goto end;
1187 
1188 		for (j = 0; j < uwsgi.cores; j++) {
1189 			struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j];
1190 			if (uwsgi_stats_object_open(us))
1191 				goto end;
1192 			if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j))
1193 				goto end;
1194 
1195 			if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests))
1196 				goto end;
1197 
1198 			if (uwsgi_stats_keylong_comma(us, "static_requests", (unsigned long long) uc->static_requests))
1199 				goto end;
1200 
1201 			if (uwsgi_stats_keylong_comma(us, "routed_requests", (unsigned long long) uc->routed_requests))
1202 				goto end;
1203 
1204 			if (uwsgi_stats_keylong_comma(us, "offloaded_requests", (unsigned long long) uc->offloaded_requests))
1205 				goto end;
1206 
1207 			if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
1208 				goto end;
1209 
1210 			if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
1211 				goto end;
1212 
1213 			if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
1214 				goto end;
1215 
1216 			if (uwsgi_stats_key(us, "vars"))
1217 				goto end;
1218 
1219 			if (uwsgi_stats_list_open(us))
1220                         	goto end;
1221 
1222 			if (uwsgi_stats_dump_vars(us, uc)) goto end;
1223 
1224 			if (uwsgi_stats_list_close(us))
1225 				goto end;
1226 
1227 			if (uwsgi_stats_comma(us)) goto end;
1228 
1229 			if (uwsgi_stats_key(us, "req_info"))
1230 				goto end;
1231 
1232 			if (uwsgi_stats_object_open(us))
1233 				goto end;
1234 
1235 			if (uwsgi_stats_dump_request(us, uc)) goto end;
1236 
1237 			if (uwsgi_stats_object_close(us))
1238 				goto end;
1239 
1240 			if (uwsgi_stats_object_close(us))
1241 				goto end;
1242 
1243 			if (j < uwsgi.cores - 1) {
1244 				if (uwsgi_stats_comma(us))
1245 					goto end;
1246 			}
1247 		}
1248 
1249 		if (uwsgi_stats_list_close(us))
1250 			goto end;
1251 
1252 nocores:
1253 
1254 		if (uwsgi_stats_object_close(us))
1255 			goto end;
1256 
1257 
1258 		if (i < uwsgi.numproc - 1) {
1259 			if (uwsgi_stats_comma(us))
1260 				goto end;
1261 		}
1262 	}
1263 
1264 	if (uwsgi_stats_list_close(us))
1265 		goto end;
1266 
1267 	struct uwsgi_spooler *uspool = uwsgi.spoolers;
1268 	if (uspool) {
1269 		if (uwsgi_stats_comma(us))
1270 			goto end;
1271 		if (uwsgi_stats_key(us, "spoolers"))
1272 			goto end;
1273 		if (uwsgi_stats_list_open(us))
1274 			goto end;
1275 		while (uspool) {
1276 			if (uwsgi_stats_object_open(us))
1277 				goto end;
1278 
1279 			if (uwsgi_stats_keyval_comma(us, "dir", uspool->dir))
1280 				goto end;
1281 
1282 			if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uspool->pid))
1283 				goto end;
1284 
1285 			if (uwsgi_stats_keylong_comma(us, "tasks", (unsigned long long) uspool->tasks))
1286 				goto end;
1287 
1288 			if (uwsgi_stats_keylong_comma(us, "respawns", (unsigned long long) uspool->respawned))
1289 				goto end;
1290 
1291 			if (uwsgi_stats_keylong(us, "running", (unsigned long long) uspool->running))
1292 				goto end;
1293 
1294 			if (uwsgi_stats_object_close(us))
1295 				goto end;
1296 			uspool = uspool->next;
1297 			if (uspool) {
1298 				if (uwsgi_stats_comma(us))
1299 					goto end;
1300 			}
1301 		}
1302 		if (uwsgi_stats_list_close(us))
1303 			goto end;
1304 	}
1305 
1306 	struct uwsgi_cron *ucron = uwsgi.crons;
1307 	if (ucron) {
1308 		if (uwsgi_stats_comma(us))
1309 			goto end;
1310 		if (uwsgi_stats_key(us, "crons"))
1311 			goto end;
1312 		if (uwsgi_stats_list_open(us))
1313 			goto end;
1314 		while (ucron) {
1315 			if (uwsgi_stats_object_open(us))
1316 				goto end;
1317 
1318 			if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
1319 				goto end;
1320 
1321 			if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
1322 				goto end;
1323 
1324 			if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
1325 				goto end;
1326 
1327 			if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
1328 				goto end;
1329 
1330 			if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
1331 				goto end;
1332 
1333 			char *cmd = uwsgi_malloc((strlen(ucron->command)*2)+1);
1334 			escape_json(ucron->command, strlen(ucron->command), cmd);
1335 			if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
1336 				free(cmd);
1337 				goto end;
1338 			}
1339 			free(cmd);
1340 
1341 			if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
1342 				goto end;
1343 
1344 #ifdef UWSGI_SSL
1345 			if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
1346 				goto end;
1347 #endif
1348 
1349 			if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
1350 				goto end;
1351 
1352 			if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
1353 				goto end;
1354 
1355 			if (uwsgi_stats_object_close(us))
1356 				goto end;
1357 
1358 			ucron = ucron->next;
1359 			if (ucron) {
1360 				if (uwsgi_stats_comma(us))
1361 					goto end;
1362 			}
1363 		}
1364 		if (uwsgi_stats_list_close(us))
1365 			goto end;
1366 	}
1367 
1368 #ifdef UWSGI_SSL
1369 	struct uwsgi_legion *legion = NULL;
1370 	if (uwsgi.legions) {
1371 
1372 		if (uwsgi_stats_comma(us))
1373 			goto end;
1374 
1375 		if (uwsgi_stats_key(us, "legions"))
1376 			goto end;
1377 
1378 		if (uwsgi_stats_list_open(us))
1379 			goto end;
1380 
1381 		legion = uwsgi.legions;
1382 		while (legion) {
1383 			if (uwsgi_stats_object_open(us))
1384 				goto end;
1385 
1386 			if (uwsgi_stats_keyval_comma(us, "legion", legion->legion))
1387 				goto end;
1388 
1389 			if (uwsgi_stats_keyval_comma(us, "addr", legion->addr))
1390 				goto end;
1391 
1392 			if (uwsgi_stats_keyval_comma(us, "uuid", legion->uuid))
1393 				goto end;
1394 
1395 			if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) legion->valor))
1396 				goto end;
1397 
1398 			if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) legion->checksum))
1399 				goto end;
1400 
1401 			if (uwsgi_stats_keylong_comma(us, "quorum", (unsigned long long) legion->quorum))
1402 				goto end;
1403 
1404 			if (uwsgi_stats_keylong_comma(us, "i_am_the_lord", (unsigned long long) legion->i_am_the_lord))
1405 				goto end;
1406 
1407 			if (uwsgi_stats_keylong_comma(us, "lord_valor", (unsigned long long) legion->lord_valor))
1408 				goto end;
1409 
1410 			if (uwsgi_stats_keyvaln_comma(us, "lord_uuid", legion->lord_uuid, 36))
1411 				goto end;
1412 
1413 			// legion nodes start
1414 			if (uwsgi_stats_key(us, "nodes"))
1415                                 goto end;
1416 
1417                         if (uwsgi_stats_list_open(us))
1418                                 goto end;
1419 
1420                         struct uwsgi_string_list *nodes = legion->nodes;
1421                         while (nodes) {
1422 
1423 				if (uwsgi_stats_str(us, nodes->value))
1424                                 	goto end;
1425 
1426                                 nodes = nodes->next;
1427                                 if (nodes) {
1428                                         if (uwsgi_stats_comma(us))
1429                                                 goto end;
1430                                 }
1431                         }
1432 
1433 			if (uwsgi_stats_list_close(us))
1434 				goto end;
1435 
1436                         if (uwsgi_stats_comma(us))
1437                         	goto end;
1438 
1439 
1440 			// legion members start
1441 			if (uwsgi_stats_key(us, "members"))
1442 				goto end;
1443 
1444 			if (uwsgi_stats_list_open(us))
1445 				goto end;
1446 
1447 			uwsgi_rlock(legion->lock);
1448 			struct uwsgi_legion_node *node = legion->nodes_head;
1449 			while (node) {
1450 				if (uwsgi_stats_object_open(us))
1451 					goto unlock_legion_mutex;
1452 
1453 				if (uwsgi_stats_keyvaln_comma(us, "name", node->name, node->name_len))
1454 					goto unlock_legion_mutex;
1455 
1456 				if (uwsgi_stats_keyval_comma(us, "uuid", node->uuid))
1457 					goto unlock_legion_mutex;
1458 
1459 				if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) node->valor))
1460 					goto unlock_legion_mutex;
1461 
1462 				if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) node->checksum))
1463 					goto unlock_legion_mutex;
1464 
1465 				if (uwsgi_stats_keylong(us, "last_seen", (unsigned long long) node->last_seen))
1466 					goto unlock_legion_mutex;
1467 
1468 				if (uwsgi_stats_object_close(us))
1469 					goto unlock_legion_mutex;
1470 
1471 				node = node->next;
1472 				if (node) {
1473 					if (uwsgi_stats_comma(us))
1474 						goto unlock_legion_mutex;
1475 				}
1476 			}
1477 			uwsgi_rwunlock(legion->lock);
1478 
1479 			if (uwsgi_stats_list_close(us))
1480 				goto end;
1481 			// legion nodes end
1482 
1483 			if (uwsgi_stats_object_close(us))
1484 				goto end;
1485 
1486 			legion = legion->next;
1487 			if (legion) {
1488 				if (uwsgi_stats_comma(us))
1489 					goto end;
1490 			}
1491 		}
1492 
1493 		if (uwsgi_stats_list_close(us))
1494 			goto end;
1495 
1496 	}
1497 #endif
1498 
1499 	if (uwsgi_stats_object_close(us))
1500 		goto end;
1501 
1502 	return us;
1503 #ifdef UWSGI_SSL
1504 unlock_legion_mutex:
1505 	if (legion)
1506 		uwsgi_rwunlock(legion->lock);
1507 #endif
1508 end:
1509 	free(us->base);
1510 	free(us);
1511 	return NULL;
1512 }
1513 
uwsgi_register_cheaper_algo(char * name,int (* func)(int))1514 void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
1515 
1516 	struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
1517 
1518 	if (!uca) {
1519 		uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
1520 		uca = uwsgi.cheaper_algos;
1521 	}
1522 	else {
1523 		while (uca) {
1524 			if (!uca->next) {
1525 				uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
1526 				uca = uca->next;
1527 				break;
1528 			}
1529 			uca = uca->next;
1530 		}
1531 
1532 	}
1533 
1534 	uca->name = name;
1535 	uca->func = func;
1536 	uca->next = NULL;
1537 
1538 #ifdef UWSGI_DEBUG
1539 	uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
1540 #endif
1541 }
1542 
trigger_harakiri(int i)1543 void trigger_harakiri(int i) {
1544 	int j;
1545 	uwsgi_log_verbose("*** HARAKIRI ON WORKER %d (pid: %d, try: %d) ***\n", i, uwsgi.workers[i].pid, uwsgi.workers[i].pending_harakiri + 1);
1546 	if (uwsgi.harakiri_verbose) {
1547 #ifdef __linux__
1548 		int proc_file;
1549 		char proc_buf[4096];
1550 		char proc_name[64];
1551 		ssize_t proc_len;
1552 
1553 		if (snprintf(proc_name, 64, "/proc/%d/syscall", uwsgi.workers[i].pid) > 0) {
1554 			memset(proc_buf, 0, 4096);
1555 			proc_file = open(proc_name, O_RDONLY);
1556 			if (proc_file >= 0) {
1557 				proc_len = read(proc_file, proc_buf, 4096);
1558 				if (proc_len > 0) {
1559 					uwsgi_log("HARAKIRI: -- syscall> %s", proc_buf);
1560 				}
1561 				close(proc_file);
1562 			}
1563 		}
1564 
1565 		if (snprintf(proc_name, 64, "/proc/%d/wchan", uwsgi.workers[i].pid) > 0) {
1566 			memset(proc_buf, 0, 4096);
1567 
1568 			proc_file = open(proc_name, O_RDONLY);
1569 			if (proc_file >= 0) {
1570 				proc_len = read(proc_file, proc_buf, 4096);
1571 				if (proc_len > 0) {
1572 					uwsgi_log("HARAKIRI: -- wchan> %s\n", proc_buf);
1573 				}
1574 				close(proc_file);
1575 			}
1576 		}
1577 
1578 #endif
1579 	}
1580 
1581 	if (uwsgi.workers[i].pid > 0) {
1582 		for (j = 0; j < uwsgi.gp_cnt; j++) {
1583 			if (uwsgi.gp[j]->harakiri) {
1584 				uwsgi.gp[j]->harakiri(i);
1585 			}
1586 		}
1587 		for (j = 0; j < 256; j++) {
1588 			if (uwsgi.p[j]->harakiri) {
1589 				uwsgi.p[j]->harakiri(i);
1590 			}
1591 		}
1592 
1593 		uwsgi_dump_worker(i, "HARAKIRI");
1594 		kill(uwsgi.workers[i].pid, SIGKILL);
1595 		if (!uwsgi.workers[i].pending_harakiri)
1596 			uwsgi.workers[i].harakiri_count++;
1597 		uwsgi.workers[i].pending_harakiri++;
1598 	}
1599 
1600 }
1601 
uwsgi_master_fix_request_counters()1602 void uwsgi_master_fix_request_counters() {
1603 	int i;
1604 	uint64_t total_counter = 0;
1605         for (i = 1; i <= uwsgi.numproc;i++) {
1606 		uint64_t tmp_counter = 0;
1607 		int j;
1608 		for(j=0;j<uwsgi.cores;j++) {
1609 			tmp_counter += uwsgi.workers[i].cores[j].requests;
1610 		}
1611 		uwsgi.workers[i].requests = tmp_counter;
1612 		total_counter += tmp_counter;
1613 	}
1614 
1615 	uwsgi.workers[0].requests = total_counter;
1616 }
1617 
1618 
uwsgi_cron_task_needs_execution(struct tm * uwsgi_cron_delta,int minute,int hour,int day,int month,int week)1619 int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
1620 
1621 	int uc_minute, uc_hour, uc_day, uc_month, uc_week;
1622 
1623 	uc_minute = minute;
1624 	uc_hour = hour;
1625 	uc_day = day;
1626 	uc_month = month;
1627 	// support 7 as alias for sunday (0) to match crontab behaviour
1628 	uc_week = week == 7 ? 0 : week;
1629 
1630 	// negative values as interval -1 = * , -5 = */5
1631 	if (minute < 0) {
1632 		if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
1633 			uc_minute = uwsgi_cron_delta->tm_min;
1634 		}
1635 	}
1636 	if (hour < 0) {
1637 		if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
1638 			uc_hour = uwsgi_cron_delta->tm_hour;
1639 		}
1640 	}
1641 	if (month < 0) {
1642 		if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
1643 			uc_month = uwsgi_cron_delta->tm_mon;
1644 		}
1645 	}
1646 	if (day < 0) {
1647 		if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
1648 			uc_day = uwsgi_cron_delta->tm_mday;
1649 		}
1650 	}
1651 	if (week < 0) {
1652 		if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
1653 			uc_week = uwsgi_cron_delta->tm_wday;
1654 		}
1655 	}
1656 
1657 	int run_task = 0;
1658 	// mday and wday are ORed
1659 	if (day >= 0 && week >= 0) {
1660 		if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
1661 			run_task = 1;
1662 		}
1663 	}
1664 	else {
1665 		if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
1666 			run_task = 1;
1667 		}
1668 	}
1669 
1670 	return run_task;
1671 
1672 }
1673 
add_reload_fds(struct uwsgi_string_list * list,char * type)1674 static void add_reload_fds(struct uwsgi_string_list *list, char *type) {
1675 	struct uwsgi_string_list *usl = list;
1676 	while(usl) {
1677 		char *strc = uwsgi_str(usl->value);
1678 		char *space = strchr(strc, ' ');
1679 		if (space) {
1680 			*space = 0;
1681 			usl->custom_ptr = space+1;
1682 		}
1683 		char *colon = strchr(strc, ':');
1684 		if (colon) {
1685 			*colon = 0;
1686 			usl->custom2 = strtoul(colon+1, NULL, 10);
1687 		}
1688 		usl->custom = strtoul(strc, NULL, 10);
1689 		if (!usl->custom2) usl->custom2 = 1;
1690 		event_queue_add_fd_read(uwsgi.master_queue, usl->custom);
1691 		uwsgi_add_safe_fd(usl->custom);
1692 		uwsgi_log("added %s reload monitor for fd %d (read size: %llu)\n", type, (int) usl->custom, usl->custom2);
1693 		usl = usl->next;
1694 	}
1695 }
1696 
uwsgi_add_reload_fds()1697 void uwsgi_add_reload_fds() {
1698 	add_reload_fds(uwsgi.reload_on_fd, "graceful");
1699 	add_reload_fds(uwsgi.brutal_reload_on_fd, "brutal");
1700 }
1701 
uwsgi_refork_master()1702 void uwsgi_refork_master() {
1703 	pid_t pid = fork();
1704 	if (pid < 0) {
1705 		uwsgi_error("uwsgi_refork_master()/fork()");
1706 		return;
1707 	}
1708 
1709 	if (pid > 0) {
1710 		uwsgi_log_verbose("new master copy spawned with pid %d\n", (int) pid);
1711 		return;
1712 	}
1713 
1714 	// detach from the old master
1715 	setsid();
1716 
1717 	uwsgi.master_is_reforked = 1;
1718 	uwsgi_reload(uwsgi.argv);
1719 	// never here
1720 	exit(1);
1721 }
1722 
uwsgi_cheaper_increase()1723 void uwsgi_cheaper_increase() {
1724 	uwsgi.cheaper_fifo_delta++;
1725 }
1726 
uwsgi_cheaper_decrease()1727 void uwsgi_cheaper_decrease() {
1728         uwsgi.cheaper_fifo_delta--;
1729 }
1730 
uwsgi_go_cheap()1731 void uwsgi_go_cheap() {
1732 	int i;
1733 	int waitpid_status;
1734 	if (uwsgi.status.is_cheap) return;
1735 	uwsgi_log_verbose("going cheap...\n");
1736 	uwsgi.status.is_cheap = 1;
1737                 for (i = 1; i <= uwsgi.numproc; i++) {
1738                         uwsgi.workers[i].cheaped = 1;
1739 			uwsgi.workers[i].rss_size = 0;
1740         		uwsgi.workers[i].vsz_size = 0;
1741                         if (uwsgi.workers[i].pid == 0)
1742                                 continue;
1743 			uwsgi_log("killing worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
1744                         kill(uwsgi.workers[i].pid, SIGKILL);
1745                         if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
1746                                 if (errno != ECHILD)
1747                                         uwsgi_error("uwsgi_go_cheap()/waitpid()");
1748                         }
1749                 }
1750                 uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
1751                 uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
1752 }
1753 
1754 #ifdef __linux__
uwsgi_setns_preopen()1755 void uwsgi_setns_preopen() {
1756 	struct dirent *de;
1757         DIR *ns = opendir("/proc/self/ns");
1758         if (!ns) {
1759                 uwsgi_error("uwsgi_setns_preopen()/opendir()");
1760 		exit(1);
1761         }
1762         while ((de = readdir(ns)) != NULL) {
1763                 if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
1764 		if (!strcmp(de->d_name, "user")) continue;
1765                 struct uwsgi_string_list *usl = NULL;
1766                 int found = 0;
1767                 uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
1768                         if (!strcmp(de->d_name, usl->value)) {
1769                                 found = 1;
1770                                 break;
1771                         }
1772                 }
1773                 if (found) continue;
1774                 char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
1775                 uwsgi.setns_fds[uwsgi.setns_fds_count] = open(filename, O_RDONLY);
1776                 if (uwsgi.setns_fds[uwsgi.setns_fds_count] < 0) {
1777                         uwsgi_error_open(filename);
1778                         free(filename);
1779 			exit(1);
1780                 }
1781                 free(filename);
1782                 uwsgi.setns_fds_count++;
1783         }
1784 	closedir(ns);
1785 }
uwsgi_master_manage_setns(int fd)1786 void uwsgi_master_manage_setns(int fd) {
1787 
1788         struct sockaddr_un snsun;
1789         socklen_t snsun_len = sizeof(struct sockaddr_un);
1790 
1791         int setns_client = accept(fd, (struct sockaddr *) &snsun, &snsun_len);
1792         if (setns_client < 0) {
1793                 uwsgi_error("uwsgi_master_manage_setns()/accept()");
1794                 return;
1795         }
1796 
1797 	int i;
1798 	int tmp_fds[64];
1799 	int *fds = tmp_fds;
1800         int num_fds = 0;
1801 
1802 	struct msghdr sn_msg;
1803         void *sn_msg_control;
1804         struct iovec sn_iov[2];
1805         struct cmsghdr *cmsg;
1806 	DIR *ns = NULL;
1807 
1808 	if (uwsgi.setns_fds_count) {
1809 		fds = uwsgi.setns_fds;
1810 		num_fds = uwsgi.setns_fds_count;
1811 		goto send;
1812 	}
1813 
1814 	struct dirent *de;
1815 	ns = opendir("/proc/self/ns");
1816 	if (!ns) {
1817 		close(setns_client);
1818 		uwsgi_error("uwsgi_master_manage_setns()/opendir()");
1819 		return;
1820 	}
1821 	while ((de = readdir(ns)) != NULL) {
1822 		if (strlen(de->d_name) > 0 && de->d_name[0] == '.') continue;
1823 		if (!strcmp(de->d_name, "user")) continue;
1824 		struct uwsgi_string_list *usl = NULL;
1825 		int found = 0;
1826 		uwsgi_foreach(usl, uwsgi.setns_socket_skip) {
1827 			if (!strcmp(de->d_name, usl->value)) {
1828 				found = 1;
1829 				break;
1830 			}
1831 		}
1832 		if (found) continue;
1833 		char *filename = uwsgi_concat2("/proc/self/ns/", de->d_name);
1834 		fds[num_fds] = open(filename, O_RDONLY);
1835 		if (fds[num_fds] < 0) {
1836 			uwsgi_error_open(filename);
1837 			free(filename);
1838 			goto clear;
1839 		}
1840 		free(filename);
1841 		num_fds++;
1842 	}
1843 
1844 send:
1845 
1846         sn_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
1847 
1848         sn_iov[0].iov_base = "uwsgi-setns";
1849         sn_iov[0].iov_len = 11;
1850         sn_iov[1].iov_base = &num_fds;
1851         sn_iov[1].iov_len = sizeof(int);
1852 
1853         sn_msg.msg_name = NULL;
1854         sn_msg.msg_namelen = 0;
1855 
1856         sn_msg.msg_iov = sn_iov;
1857         sn_msg.msg_iovlen = 2;
1858 
1859         sn_msg.msg_flags = 0;
1860         sn_msg.msg_control = sn_msg_control;
1861         sn_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
1862 
1863         cmsg = CMSG_FIRSTHDR(&sn_msg);
1864         cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
1865         cmsg->cmsg_level = SOL_SOCKET;
1866         cmsg->cmsg_type = SCM_RIGHTS;
1867 
1868         int *sn_fd_ptr = (int *) CMSG_DATA(cmsg);
1869 	for(i=0;i<num_fds;i++) {
1870 		sn_fd_ptr[i] = fds[i];
1871 	}
1872 
1873         if (sendmsg(setns_client, &sn_msg, 0) < 0) {
1874                 uwsgi_error("uwsgi_master_manage_setns()/sendmsg()");
1875         }
1876 
1877         free(sn_msg_control);
1878 
1879 clear:
1880 	close(setns_client);
1881 	if (ns) {
1882 		closedir(ns);
1883 		for(i=0;i<num_fds;i++) {
1884 			close(fds[i]);
1885 		}
1886 	}
1887 }
1888 
1889 #endif
1890 
1891 /*
1892 	this is racey, but the worst thing would be printing garbage in the logs...
1893 */
uwsgi_dump_worker(int wid,char * msg)1894 void uwsgi_dump_worker(int wid, char *msg) {
1895 	int i;
1896 	uwsgi_log_verbose("%s !!! worker %d status !!!\n", msg, wid);
1897 	for(i=0;i<uwsgi.cores;i++) {
1898 		struct uwsgi_core *uc = &uwsgi.workers[wid].cores[i];
1899 		struct wsgi_request *wsgi_req = &uc->req;
1900 		if (uc->in_request) {
1901 			uwsgi_log_verbose("%s [core %d] %.*s - %.*s %.*s since %llu\n", msg, i, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) (wsgi_req->start_of_request/(1000*1000)));
1902 		}
1903 	}
1904 	uwsgi_log_verbose("%s !!! end of worker %d status !!!\n",msg, wid);
1905 }
1906