Backend Development 14 min read

Understanding Nginx Process Management: Signals, Master‑Worker Loops, and Worker Initialization

This article explains how Nginx creates and controls its master and worker processes using Linux signals, global flag variables, and a series of initialization steps—including signal handling, process spawning, socketpair communication, and worker loop execution—to achieve robust, high‑concurrency request handling.

Xueersi Online School Tech Team
Xueersi Online School Tech Team
Xueersi Online School Tech Team
Understanding Nginx Process Management: Signals, Master‑Worker Loops, and Worker Initialization

The article continues the walkthrough of Nginx startup by focusing on how the master process creates and manages worker processes, how signals are handled, and how global flag variables drive the behavior of both master and worker loops.

1. Signals and Global Flags

Nginx redefines handlers for several Linux signals (e.g., SIGCHLD, SIGTERM, SIGINT, SIGHUP, USR1, USR2, WINCH) via ngx_signal_handler . Each signal sets a corresponding global flag such as ngx_quit , ngx_terminate , ngx_reconfigure , etc., which the master and worker processes poll in their main loops to decide actions like graceful shutdown, reload, or binary upgrade.

static void ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext) {
    …
    switch (ngx_process) {
        case NGX_PROCESS_MASTER:
        case NGX_PROCESS_SINGLE:
            switch (signo) {
                case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
                    ngx_quit = 1;
                    break;
                case ngx_signal_value(NGX_TERMINATE_SIGNAL):
                case SIGINT:
                    ngx_terminate = 1;
                    break;
                case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
                    if (ngx_daemonized) {
                        ngx_noaccept = 1;
                        action = ", stop accepting connections";
                    }
                    break;
                case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
                    ngx_reconfigure = 1;
                    break;
                case ngx_signal_value(NGX_REOPEN_SIGNAL):
                    ngx_reopen = 1;
                    break;
                case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
                    ngx_change_binary = 1;
                    break;
                case SIGALRM:
                    ngx_sigalrm = 1;
                    break;
                case SIGIO:
                    ngx_sigio = 1;
                    break;
                case SIGCHLD:
                    ngx_reap = 1;
                    break;
            }
            break;
        …
    }
}

2. Master Process Work Cycle

The master process runs ngx_master_process_cycle , which first masks signals with sigprocmask , then starts workers, cache manager, and privileged agent processes. Workers are launched via ngx_start_worker_processes , which internally calls ngx_spawn_process (a wrapper around fork ) and sets up a socketpair for parent‑child communication.

ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
    char *name, ngx_int_t respawn) {
    u_long on;
    ngx_pid_t pid;
    ngx_int_t s;
    …
    if (respawn >= 0) {
        s = respawn;
    } else {
        for (s = 0; s < ngx_last_process; s++) {
            if (ngx_processes[s].pid == -1) {
                break;
            }
        }
        if (s == NGX_MAX_PROCESSES) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "no more than %d processes can be spawned",
                          NGX_MAX_PROCESSES);
            return NGX_INVALID_PID;
        }
    }
    if (respawn != NGX_PROCESS_DETACHED) {
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "socketpair() failed while spawning \"%s\"", name);
            return NGX_INVALID_PID;
        }
        // set non‑blocking, async, close‑on‑exec flags …
    }
    pid = fork();
    switch (pid) {
        case -1:
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "fork() failed while spawning \"%s\"", name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        case 0:
            ngx_parent = ngx_pid;
            ngx_pid = ngx_getpid();
            proc(cycle, data);
            break;
        default:
            break;
    }
    return pid;
}

The ngx_process_t structure stores each child’s PID, status, communication channel, and flags such as respawn , just_spawn , detached , exiting , and exited :

typedef struct {
    ngx_pid_t           pid;         // process pid
    int                 status;      // status from waitpid
    ngx_socket_t        channel[2];   // parent‑child sockets
    ngx_spawn_proc_pt   proc;        // child work routine
    char               *name;        // process name
    unsigned            respawn:1;    // need to respawn
    unsigned            just_spawn:1; // currently spawning
    unsigned            detached:1;   // detached from parent
    unsigned            exiting:1;    // exiting flag
    unsigned            exited:1;     // exited flag
} ngx_process_t;

3. Worker Process Work Cycle

Workers execute ngx_worker_process_cycle . They first run ngx_worker_process_init to set environment, CPU affinity, and resource limits, then repeatedly check global flags ( ngx_quit , ngx_terminate , ngx_exiting ) to decide whether to shut down gracefully or immediately. The core of the worker is ngx_process_events_and_timers , which handles network events, timers, and post‑events using Nginx’s event‑driven architecture.

4. Overall Startup Flow

The complete startup consists of two phases: (1) creation and initialization of the core ngx_cycle_t structure, which parses configuration files; (2) spawning the master process and its workers, then entering their respective loops. The master monitors signals and global flags, while workers handle actual client connections.

5. Summary

This chapter provides a concise overview of Nginx’s initialization, signal handling, master‑worker process creation, and the key flag‑driven loops that enable graceful reloads, hot upgrades, and robust high‑concurrency request processing.

Backendprocess managementnginxSignalsmaster worker
Xueersi Online School Tech Team
Written by

Xueersi Online School Tech Team

The Xueersi Online School Tech Team, dedicated to innovating and promoting internet education technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.