Why Does Linux Show “Out of Memory” When PID Allocation Fails?
A Linux server repeatedly reports “fork: cannot allocate memory” not because RAM is exhausted but due to excessive Java threads causing PID allocation failures, and the kernel mistakenly maps those failures to the ENOMEM error code.
1. Underlying Process Creation Analysis
The error message "fork: cannot allocate memory" misleads users into thinking physical memory is insufficient, while the real cause can be PID allocation failure when too many processes or threads exist.
The server runs CentOS 7.8 with kernel 3.10.0-1127.
1.1 do_fork Dissection
Both process and thread creation in the Linux kernel eventually invoke do_fork, which copies the current task's data structures to create a new task_struct.
// file: kernel/fork.c
long do_fork(unsigned long clone_flags, ...)
{
// copy_process performs the heavy lifting
p = copy_process(clone_flags, stack_start, stack_size,
child_tidptr, NULL, trace);
...
}The core of the creation logic resides in copy_process, which allocates the new task's kernel objects.
// file: kernel/fork.c
static struct task_struct *copy_process(unsigned long clone_flags, ...)
{
struct task_struct *p;
// allocate PID
if (pid != &init_struct_pid) {
retval = -ENOMEM;
pid = alloc_pid(p->nsproxy->pid_ns);
if (!pid)
goto bad_fork_cleanup_io;
}
p->pid = pid_nr(pid);
p->tgid = p->pid;
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
...
bad_fork_cleanup_io:
if (p->io_context)
exit_io_context(p);
...
return ERR_PTR(retval);
}Notice that the error code is set to -ENOMEM before attempting alloc_pid, meaning any failure in PID allocation is reported as an out‑of‑memory condition.
1.2 Why alloc_pid Can Fail
alloc_pidmay fail for two reasons:
Memory allocation for the struct pid object fails.
Allocation of a numeric PID via alloc_pidmap fails (e.g., PID namespace exhaustion).
Both paths return -ENOMEM, even when the underlying problem is not memory shortage.
// file: kernel/pid.c
struct pid *alloc_pid(struct pid_namespace *ns)
{
// allocate pid object
pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL);
if (!pid)
goto out;
// allocate numeric PID(s)
for (i = ns->level; i >= 0; i--) {
nr = alloc_pidmap(tmp);
if (nr < 0)
goto out_free;
pid->numbers[i].nr = nr;
pid->numbers[i].ns = tmp;
tmp = tmp->parent;
}
...
out:
return pid;
out_free:
goto out;
}The kernel represents a PID as a small structure ( struct pid) rather than a plain integer, requiring memory for the object and potentially multiple numeric IDs when namespaces are involved (e.g., a container process gets both a container‑local PID and a host PID).
When many Java processes spawn excessive threads, the system can exhaust the available PID numbers, triggering the alloc_pid failure and consequently the misleading ENOMEM error.
2. Does a New Kernel Version Fix the Issue?
The author compared the old 3.10 kernel with a newer 5.16.11 source. In newer kernels the error handling in copy_process no longer hard‑codes -ENOMEM; instead it propagates the actual error returned by alloc_pid:
// file: kernel/fork.c (newer kernel)
static __latent_entropy struct task_struct *copy_process(...)
{
...
pid = alloc_pid(p->nsproxy->pid_ns_for_children, args->set_tid,
args->set_tid_size);
if (IS_ERR(pid)) {
retval = PTR_ERR(pid);
goto bad_fork_cleanup_thread;
}
...
}However, the upstream alloc_pid still defaults to returning -ENOMEM for PID‑namespace failures, as explained in its comment:
// file: include/pid.c
/*
* ENOMEM is not the most obvious choice, especially when the child
* subreaper has already exited and the PID namespace denies creation
* of new processes. But ENOMEM is what we have exposed to userspace for
* a long time and it is documented behavior for PID namespaces. So we
* can't easily change it even if a better error code exists.
*/
retval = -ENOMEM;Thus, even recent kernels retain the misleading error mapping.
Conclusion
When Linux reports “cannot allocate memory” during a fork, the real culprit may be PID exhaustion caused by an excessive number of processes or threads, not actual RAM shortage. Administrators should first check the process/thread count and, if necessary, increase /proc/sys/kernel/pid_max or eliminate unnecessary processes.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
