Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_channel.h>
0012 
0013 
0014 typedef struct {
0015     int     signo;
0016     char   *signame;
0017     char   *name;
0018     void  (*handler)(int signo, siginfo_t *siginfo, void *ucontext);
0019 } ngx_signal_t;
0020 
0021 
0022 
0023 static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
0024 static void ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext);
0025 static void ngx_process_get_status(void);
0026 static void ngx_unlock_mutexes(ngx_pid_t pid);
0027 
0028 
0029 int              ngx_argc;
0030 char           **ngx_argv;
0031 char           **ngx_os_argv;
0032 
0033 ngx_int_t        ngx_process_slot;
0034 ngx_socket_t     ngx_channel;
0035 ngx_int_t        ngx_last_process;
0036 ngx_process_t    ngx_processes[NGX_MAX_PROCESSES];
0037 
0038 
0039 ngx_signal_t  signals[] = {
0040     { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
0041       "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
0042       "reload",
0043       ngx_signal_handler },
0044 
0045     { ngx_signal_value(NGX_REOPEN_SIGNAL),
0046       "SIG" ngx_value(NGX_REOPEN_SIGNAL),
0047       "reopen",
0048       ngx_signal_handler },
0049 
0050     { ngx_signal_value(NGX_NOACCEPT_SIGNAL),
0051       "SIG" ngx_value(NGX_NOACCEPT_SIGNAL),
0052       "",
0053       ngx_signal_handler },
0054 
0055     { ngx_signal_value(NGX_TERMINATE_SIGNAL),
0056       "SIG" ngx_value(NGX_TERMINATE_SIGNAL),
0057       "stop",
0058       ngx_signal_handler },
0059 
0060     { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
0061       "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
0062       "quit",
0063       ngx_signal_handler },
0064 
0065     { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
0066       "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
0067       "",
0068       ngx_signal_handler },
0069 
0070     { SIGALRM, "SIGALRM", "", ngx_signal_handler },
0071 
0072     { SIGINT, "SIGINT", "", ngx_signal_handler },
0073 
0074     { SIGIO, "SIGIO", "", ngx_signal_handler },
0075 
0076     { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },
0077 
0078     { SIGSYS, "SIGSYS, SIG_IGN", "", NULL },
0079 
0080     { SIGPIPE, "SIGPIPE, SIG_IGN", "", NULL },
0081 
0082     { 0, NULL, "", NULL }
0083 };
0084 
0085 
0086 ngx_pid_t
0087 ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
0088     char *name, ngx_int_t respawn)
0089 {
0090     u_long     on;
0091     ngx_pid_t  pid;
0092     ngx_int_t  s;
0093 
0094     if (respawn >= 0) {
0095         s = respawn;
0096 
0097     } else {
0098         for (s = 0; s < ngx_last_process; s++) {
0099             if (ngx_processes[s].pid == -1) {
0100                 break;
0101             }
0102         }
0103 
0104         if (s == NGX_MAX_PROCESSES) {
0105             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0106                           "no more than %d processes can be spawned",
0107                           NGX_MAX_PROCESSES);
0108             return NGX_INVALID_PID;
0109         }
0110     }
0111 
0112 
0113     if (respawn != NGX_PROCESS_DETACHED) {
0114 
0115         /* Solaris 9 still has no AF_LOCAL */
0116 
0117         if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
0118         {
0119             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0120                           "socketpair() failed while spawning \"%s\"", name);
0121             return NGX_INVALID_PID;
0122         }
0123 
0124         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
0125                        "channel %d:%d",
0126                        ngx_processes[s].channel[0],
0127                        ngx_processes[s].channel[1]);
0128 
0129         if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
0130             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0131                           ngx_nonblocking_n " failed while spawning \"%s\"",
0132                           name);
0133             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0134             return NGX_INVALID_PID;
0135         }
0136 
0137         if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
0138             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0139                           ngx_nonblocking_n " failed while spawning \"%s\"",
0140                           name);
0141             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0142             return NGX_INVALID_PID;
0143         }
0144 
0145         on = 1;
0146         if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
0147             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0148                           "ioctl(FIOASYNC) failed while spawning \"%s\"", name);
0149             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0150             return NGX_INVALID_PID;
0151         }
0152 
0153         if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
0154             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0155                           "fcntl(F_SETOWN) failed while spawning \"%s\"", name);
0156             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0157             return NGX_INVALID_PID;
0158         }
0159 
0160         if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
0161             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0162                           "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
0163                            name);
0164             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0165             return NGX_INVALID_PID;
0166         }
0167 
0168         if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
0169             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0170                           "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
0171                            name);
0172             ngx_close_channel(ngx_processes[s].channel, cycle->log);
0173             return NGX_INVALID_PID;
0174         }
0175 
0176         ngx_channel = ngx_processes[s].channel[1];
0177 
0178     } else {
0179         ngx_processes[s].channel[0] = -1;
0180         ngx_processes[s].channel[1] = -1;
0181     }
0182 
0183     ngx_process_slot = s;
0184 
0185 
0186     pid = fork();
0187 
0188     switch (pid) {
0189 
0190     case -1:
0191         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0192                       "fork() failed while spawning \"%s\"", name);
0193         ngx_close_channel(ngx_processes[s].channel, cycle->log);
0194         return NGX_INVALID_PID;
0195 
0196     case 0:
0197         ngx_parent = ngx_pid;
0198         ngx_pid = ngx_getpid();
0199         proc(cycle, data);
0200         break;
0201 
0202     default:
0203         break;
0204     }
0205 
0206     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);
0207 
0208     ngx_processes[s].pid = pid;
0209     ngx_processes[s].exited = 0;
0210 
0211     if (respawn >= 0) {
0212         return pid;
0213     }
0214 
0215     ngx_processes[s].proc = proc;
0216     ngx_processes[s].data = data;
0217     ngx_processes[s].name = name;
0218     ngx_processes[s].exiting = 0;
0219 
0220     switch (respawn) {
0221 
0222     case NGX_PROCESS_NORESPAWN:
0223         ngx_processes[s].respawn = 0;
0224         ngx_processes[s].just_spawn = 0;
0225         ngx_processes[s].detached = 0;
0226         break;
0227 
0228     case NGX_PROCESS_JUST_SPAWN:
0229         ngx_processes[s].respawn = 0;
0230         ngx_processes[s].just_spawn = 1;
0231         ngx_processes[s].detached = 0;
0232         break;
0233 
0234     case NGX_PROCESS_RESPAWN:
0235         ngx_processes[s].respawn = 1;
0236         ngx_processes[s].just_spawn = 0;
0237         ngx_processes[s].detached = 0;
0238         break;
0239 
0240     case NGX_PROCESS_JUST_RESPAWN:
0241         ngx_processes[s].respawn = 1;
0242         ngx_processes[s].just_spawn = 1;
0243         ngx_processes[s].detached = 0;
0244         break;
0245 
0246     case NGX_PROCESS_DETACHED:
0247         ngx_processes[s].respawn = 0;
0248         ngx_processes[s].just_spawn = 0;
0249         ngx_processes[s].detached = 1;
0250         break;
0251     }
0252 
0253     if (s == ngx_last_process) {
0254         ngx_last_process++;
0255     }
0256 
0257     return pid;
0258 }
0259 
0260 
0261 ngx_pid_t
0262 ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
0263 {
0264     return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name,
0265                              NGX_PROCESS_DETACHED);
0266 }
0267 
0268 
0269 static void
0270 ngx_execute_proc(ngx_cycle_t *cycle, void *data)
0271 {
0272     ngx_exec_ctx_t  *ctx = data;
0273 
0274     if (execve(ctx->path, ctx->argv, ctx->envp) == -1) {
0275         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0276                       "execve() failed while executing %s \"%s\"",
0277                       ctx->name, ctx->path);
0278     }
0279 
0280     exit(1);
0281 }
0282 
0283 
0284 ngx_int_t
0285 ngx_init_signals(ngx_log_t *log)
0286 {
0287     ngx_signal_t      *sig;
0288     struct sigaction   sa;
0289 
0290     for (sig = signals; sig->signo != 0; sig++) {
0291         ngx_memzero(&sa, sizeof(struct sigaction));
0292 
0293         if (sig->handler) {
0294             sa.sa_sigaction = sig->handler;
0295             sa.sa_flags = SA_SIGINFO;
0296 
0297         } else {
0298             sa.sa_handler = SIG_IGN;
0299         }
0300 
0301         sigemptyset(&sa.sa_mask);
0302         if (sigaction(sig->signo, &sa, NULL) == -1) {
0303 #if (NGX_VALGRIND)
0304             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
0305                           "sigaction(%s) failed, ignored", sig->signame);
0306 #else
0307             ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
0308                           "sigaction(%s) failed", sig->signame);
0309             return NGX_ERROR;
0310 #endif
0311         }
0312     }
0313 
0314     return NGX_OK;
0315 }
0316 
0317 
0318 static void
0319 ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext)
0320 {
0321     char            *action;
0322     ngx_int_t        ignore;
0323     ngx_err_t        err;
0324     ngx_signal_t    *sig;
0325 
0326     ignore = 0;
0327 
0328     err = ngx_errno;
0329 
0330     for (sig = signals; sig->signo != 0; sig++) {
0331         if (sig->signo == signo) {
0332             break;
0333         }
0334     }
0335 
0336     ngx_time_sigsafe_update();
0337 
0338     action = "";
0339 
0340     switch (ngx_process) {
0341 
0342     case NGX_PROCESS_MASTER:
0343     case NGX_PROCESS_SINGLE:
0344         switch (signo) {
0345 
0346         case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
0347             ngx_quit = 1;
0348             action = ", shutting down";
0349             break;
0350 
0351         case ngx_signal_value(NGX_TERMINATE_SIGNAL):
0352         case SIGINT:
0353             ngx_terminate = 1;
0354             action = ", exiting";
0355             break;
0356 
0357         case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
0358             if (ngx_daemonized) {
0359                 ngx_noaccept = 1;
0360                 action = ", stop accepting connections";
0361             }
0362             break;
0363 
0364         case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
0365             ngx_reconfigure = 1;
0366             action = ", reconfiguring";
0367             break;
0368 
0369         case ngx_signal_value(NGX_REOPEN_SIGNAL):
0370             ngx_reopen = 1;
0371             action = ", reopening logs";
0372             break;
0373 
0374         case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
0375             if (ngx_getppid() == ngx_parent || ngx_new_binary > 0) {
0376 
0377                 /*
0378                  * Ignore the signal in the new binary if its parent is
0379                  * not changed, i.e. the old binary's process is still
0380                  * running.  Or ignore the signal in the old binary's
0381                  * process if the new binary's process is already running.
0382                  */
0383 
0384                 action = ", ignoring";
0385                 ignore = 1;
0386                 break;
0387             }
0388 
0389             ngx_change_binary = 1;
0390             action = ", changing binary";
0391             break;
0392 
0393         case SIGALRM:
0394             ngx_sigalrm = 1;
0395             break;
0396 
0397         case SIGIO:
0398             ngx_sigio = 1;
0399             break;
0400 
0401         case SIGCHLD:
0402             ngx_reap = 1;
0403             break;
0404         }
0405 
0406         break;
0407 
0408     case NGX_PROCESS_WORKER:
0409     case NGX_PROCESS_HELPER:
0410         switch (signo) {
0411 
0412         case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
0413             if (!ngx_daemonized) {
0414                 break;
0415             }
0416             ngx_debug_quit = 1;
0417             /* fall through */
0418         case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
0419             ngx_quit = 1;
0420             action = ", shutting down";
0421             break;
0422 
0423         case ngx_signal_value(NGX_TERMINATE_SIGNAL):
0424         case SIGINT:
0425             ngx_terminate = 1;
0426             action = ", exiting";
0427             break;
0428 
0429         case ngx_signal_value(NGX_REOPEN_SIGNAL):
0430             ngx_reopen = 1;
0431             action = ", reopening logs";
0432             break;
0433 
0434         case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
0435         case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
0436         case SIGIO:
0437             action = ", ignoring";
0438             break;
0439         }
0440 
0441         break;
0442     }
0443 
0444     if (siginfo && siginfo->si_pid) {
0445         ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
0446                       "signal %d (%s) received from %P%s",
0447                       signo, sig->signame, siginfo->si_pid, action);
0448 
0449     } else {
0450         ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
0451                       "signal %d (%s) received%s",
0452                       signo, sig->signame, action);
0453     }
0454 
0455     if (ignore) {
0456         ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0,
0457                       "the changing binary signal is ignored: "
0458                       "you should shutdown or terminate "
0459                       "before either old or new binary's process");
0460     }
0461 
0462     if (signo == SIGCHLD) {
0463         ngx_process_get_status();
0464     }
0465 
0466     ngx_set_errno(err);
0467 }
0468 
0469 
0470 static void
0471 ngx_process_get_status(void)
0472 {
0473     int              status;
0474     char            *process;
0475     ngx_pid_t        pid;
0476     ngx_err_t        err;
0477     ngx_int_t        i;
0478     ngx_uint_t       one;
0479 
0480     one = 0;
0481 
0482     for ( ;; ) {
0483         pid = waitpid(-1, &status, WNOHANG);
0484 
0485         if (pid == 0) {
0486             return;
0487         }
0488 
0489         if (pid == -1) {
0490             err = ngx_errno;
0491 
0492             if (err == NGX_EINTR) {
0493                 continue;
0494             }
0495 
0496             if (err == NGX_ECHILD && one) {
0497                 return;
0498             }
0499 
0500             /*
0501              * Solaris always calls the signal handler for each exited process
0502              * despite waitpid() may be already called for this process.
0503              *
0504              * When several processes exit at the same time FreeBSD may
0505              * erroneously call the signal handler for exited process
0506              * despite waitpid() may be already called for this process.
0507              */
0508 
0509             if (err == NGX_ECHILD) {
0510                 ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, err,
0511                               "waitpid() failed");
0512                 return;
0513             }
0514 
0515             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
0516                           "waitpid() failed");
0517             return;
0518         }
0519 
0520 
0521         one = 1;
0522         process = "unknown process";
0523 
0524         for (i = 0; i < ngx_last_process; i++) {
0525             if (ngx_processes[i].pid == pid) {
0526                 ngx_processes[i].status = status;
0527                 ngx_processes[i].exited = 1;
0528                 process = ngx_processes[i].name;
0529                 break;
0530             }
0531         }
0532 
0533         if (WTERMSIG(status)) {
0534 #ifdef WCOREDUMP
0535             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0536                           "%s %P exited on signal %d%s",
0537                           process, pid, WTERMSIG(status),
0538                           WCOREDUMP(status) ? " (core dumped)" : "");
0539 #else
0540             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0541                           "%s %P exited on signal %d",
0542                           process, pid, WTERMSIG(status));
0543 #endif
0544 
0545         } else {
0546             ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
0547                           "%s %P exited with code %d",
0548                           process, pid, WEXITSTATUS(status));
0549         }
0550 
0551         if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
0552             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0553                           "%s %P exited with fatal code %d "
0554                           "and cannot be respawned",
0555                           process, pid, WEXITSTATUS(status));
0556             ngx_processes[i].respawn = 0;
0557         }
0558 
0559         ngx_unlock_mutexes(pid);
0560     }
0561 }
0562 
0563 
0564 static void
0565 ngx_unlock_mutexes(ngx_pid_t pid)
0566 {
0567     ngx_uint_t        i;
0568     ngx_shm_zone_t   *shm_zone;
0569     ngx_list_part_t  *part;
0570     ngx_slab_pool_t  *sp;
0571 
0572     /*
0573      * unlock the accept mutex if the abnormally exited process
0574      * held it
0575      */
0576 
0577     if (ngx_accept_mutex_ptr) {
0578         (void) ngx_shmtx_force_unlock(&ngx_accept_mutex, pid);
0579     }
0580 
0581     /*
0582      * unlock shared memory mutexes if held by the abnormally exited
0583      * process
0584      */
0585 
0586     part = (ngx_list_part_t *) &ngx_cycle->shared_memory.part;
0587     shm_zone = part->elts;
0588 
0589     for (i = 0; /* void */ ; i++) {
0590 
0591         if (i >= part->nelts) {
0592             if (part->next == NULL) {
0593                 break;
0594             }
0595             part = part->next;
0596             shm_zone = part->elts;
0597             i = 0;
0598         }
0599 
0600         sp = (ngx_slab_pool_t *) shm_zone[i].shm.addr;
0601 
0602         if (ngx_shmtx_force_unlock(&sp->mutex, pid)) {
0603             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
0604                           "shared memory zone \"%V\" was locked by %P",
0605                           &shm_zone[i].shm.name, pid);
0606         }
0607     }
0608 }
0609 
0610 
0611 void
0612 ngx_debug_point(void)
0613 {
0614     ngx_core_conf_t  *ccf;
0615 
0616     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
0617                                            ngx_core_module);
0618 
0619     switch (ccf->debug_points) {
0620 
0621     case NGX_DEBUG_POINTS_STOP:
0622         raise(SIGSTOP);
0623         break;
0624 
0625     case NGX_DEBUG_POINTS_ABORT:
0626         ngx_abort();
0627     }
0628 }
0629 
0630 
0631 ngx_int_t
0632 ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_pid_t pid)
0633 {
0634     ngx_signal_t  *sig;
0635 
0636     for (sig = signals; sig->signo != 0; sig++) {
0637         if (ngx_strcmp(name, sig->name) == 0) {
0638             if (kill(pid, sig->signo) != -1) {
0639                 return 0;
0640             }
0641 
0642             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0643                           "kill(%P, %d) failed", pid, sig->signo);
0644         }
0645     }
0646 
0647     return 1;
0648 }