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