walkor/workerman · critical · RuntimeException

forkOneWorker fail

Error message

forkOneWorker fail

What it means

forkOneWorkerForLinux() spawns each worker child with pcntl_fork(); the else-branch (pid not > 0 and not 0, i.e. -1) throws this. The master could not create the worker process - OS-level fork failure, most commonly the process/PID limit (RLIMIT_NPROC or the container pids cgroup) or insufficient memory at fork time. It can hit at initial startup or when Workerman respawns a dead worker.

Source

Thrown at src/Worker.php:1766

            // Init Timer.
            Timer::init(static::$globalEvent);

            restore_error_handler();

            static::setProcessTitle('WorkerMan: worker process  ' . $worker->name . ' ' . $worker->getSocketName());
            $worker->setUserAndGroup();
            $worker->id = $id;
            $worker->run();
            // Main loop.
            static::$globalEvent->run();
            if (static::$status !== self::STATUS_SHUTDOWN) {
                $err = new Exception('event-loop exited');
                static::log($err);
                exit(250);
            }
            exit(0);
        } else {
            throw new RuntimeException("forkOneWorker fail");
        }
    }

    /**
     * Get worker id.
     *
     * @param string $workerId
     * @param int $pid
     * @return false|int|string
     */
    protected static function getId(string $workerId, int $pid): false|int|string
    {
        return array_search($pid, static::$idMap[$workerId]);
    }

    /**
     * Set unix user and group for current process.
     *

View on GitHub (pinned to 1391112a61)

Solutions

  1. Raise the ceiling: ulimit -u, docker --pids-limit, or the K8s pod-level pids limit, sized for workers x count plus headroom
  2. Audit runaway children with 'cat /sys/fs/cgroup/pids/pids.current' (or pids/pids.current in the cgroup dir) and kill leaks - worker-spawned subprocesses count against the same budget
  3. Lower total processes: reduce Worker->count or the number of Worker instances so the app fits the limit

Example fix

# before
# 10 workers x count 50 = 500 procs, pod pids limit 512
# -> RuntimeException('forkOneWorker fail') while spawning

# after
# raise the pod pid limit to 1024 (K8s: kubelet podPidsLimit or namespace limitRange)
# or reduce footprint:
#   $worker->count = 20;  // 10 x 20 = 200 procs, fits under 512
Defensive patterns

Strategy: retry

Prevention

When it happens

Trigger: Master forking many children (workers x count) until the process ceiling: e.g. 16 workers x 20 processes on a host with a low pids limit; respawn after workers die while the system is at the ceiling; cgroup pids.max reached because of a leak of grandchild processes.

Common situations: Kubernetes pods with default pid limits and high Worker->count; Docker --pids-limit set conservatively; leftover grandchild processes (spawned by workers) counting against the same cgroup; memory pressure refusing page-table copies.

Related errors


AI-assisted analysis of walkor/workerman@1391112a61 (2026-08-21). Data as JSON: /api/errors/03ea2d1f07dcef94. Report an issue: GitHub.