nginx/nginx · error

NGX_LOG_CRIT

NGX_LOG_CRIT

Error message

getsockname() of the inherited socket #%d failed

What it means

During a binary upgrade (SIGUSR2) the new master parses the NGX environment variable, which lists listening sockets inherited from the old master, and calls getsockname() on each fd to recover its address. If the syscall fails, this CRIT is logged and the socket is marked ignore=1: that fd's address is dropped from the new master's listener set.

Source

Thrown at src/core/ngx_connection.c:164

#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
    int                        timeout;
#endif
#if (NGX_HAVE_REUSEPORT)
    int                        reuseport;
#endif

    ls = cycle->listening.elts;
    for (i = 0; i < cycle->listening.nelts; i++) {

        ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t));
        if (ls[i].sockaddr == NULL) {
            return NGX_ERROR;
        }

        ls[i].socklen = sizeof(ngx_sockaddr_t);
        if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
            ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
                          "getsockname() of the inherited "
                          "socket #%d failed", ls[i].fd);
            ls[i].ignore = 1;
            continue;
        }

        if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
            ls[i].socklen = sizeof(ngx_sockaddr_t);
        }

        switch (ls[i].sockaddr->sa_family) {

#if (NGX_HAVE_INET6)
        case AF_INET6:
            ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
            len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
            break;
#endif

View on GitHub (pinned to 3f6f7824d4)

Solutions

  1. Abort the broken new master (TERM it) and either retry the upgrade with the documented 'kill -USR2 $(cat /run/nginx.pid)' flow or do a clean restart from the service manager
  2. Never set or edit NGX manually - only the value nginx itself writes is valid
  3. Inspect the old master's environment and fds: 'tr "\0" "\n" < /proc/$(cat /run/nginx.pid)/environ | grep ^NGX=' and 'ls -l /proc/<oldpid>/fd'
  4. Remove supervisors that rewrite the environment around the USR2 handoff, or switch to systemd-managed restarts for upgrades

Example fix

# before (hand-set inherited sockets - corrupts fd assumptions)
NGX='3:4;' /usr/sbin/nginx
# after (correct binary upgrade)
kill -USR2 $(cat /run/nginx.pid)
Defensive patterns

Strategy: fallback

Validate before calling

# before any USR2 upgrade, sanity-check the old master's inherited-socket environment
old=$(cat /run/nginx.pid)
tr '\0' '\n' < /proc/$old/environ | grep '^NGX='
ls -l /proc/$old/fd | awk '$NF ~ /socket/' | wc -l

Prevention

When it happens

Trigger: Starting the new binary with a stale or hand-crafted NGX variable; the old master closed the fds between the child inheriting NGX and the getsockname call; fd numbers shifted because a wrapper altered the environment; NGX pointing at non-listening fds.

Common situations: Custom upgrade scripts that copy or rewrite the environment instead of letting nginx pass NGX itself; supervisors (supervisord, custom wrappers) scrubbing env between masters; an aborted earlier upgrade leaving stale state; accidentally exporting NGX before a fresh 'nginx' start.

Related errors


AI-assisted analysis of nginx/nginx@3f6f7824d4 (2026-08-22). Data as JSON: /api/errors/0af48f00dcf25d71. Report an issue: GitHub.