[PATCH] clone.2: Document ENOSPC due to exhaused PIDs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: KJ Tsanaktsidis <ktsanaktsidis@xxxxxxxxxxx>

The clone(2) syscall (and consequently pthread_create(3)) can return
the error ENOSPC when there are no more available PIDs on the system
because the limit in /proc/sys/kernel/pid_max has been exceeded.

The code path that can cause this error to be returned is:
  * kernel/fork.c do_fork
  * calls kernel/fork.c _do_fork
  * calls kernel/fork.c copy_process
  * calls kernel/pid.c alloc_pid
  * calls lib/idr.c idr_alloc_cyclic
  * calls lib/idr.h idr_alloc
  * calls lib/idr.c idr_alloc_cmn
  * calls include/linux/radix-tree.h idr_get_free
  * calls lib/radix-tree.c idr_get_free_cmn
which looks like it can return ENOSPC when it can't grow the radix tree.
The size of this tree looks like it's determined by pid_max (full
disclaimer; I don't really understand any of the radix tree code).

This behaviour can be reproduced by running this small test program on a
system with a low value of /proc/sys/kernel/pid_max:

  #define _GNU_SOURCE
  #include <unistd.h>
  #include <sys/syscall.h>
  #include <stdio.h>
  #include <errno.h>
  #include <sched.h>
  #include <string.h>

  int main() {
      int n_children_created = 0;
      int fail_errno = 0;
      while (1) {
          int result = syscall(SYS_clone,
              CLONE_FILES | CLONE_FS | CLONE_IO | CLONE_SYSVSEM,
              0, 0, 0, 0
          );
          if (result == 0) {
              return 0; // Child; just exit
          } else if (result == -1) {
              fail_errno = errno;
              break; // Failed; print our message.
          } else {
              n_children_created++;
          }
      }
      printf(
          "Got a clone(2) failure; %d (%s). Made %d children.\n",
          fail_errno, strerror(fail_errno), n_children_created
      );
      return 0;
  }

  $ cat /proc/sys/kernel/pid_max
  30000
  $ gcc clonetest.c -o clonetest
  $ ./clonetest
  Got a clone(2) failure; 28 (No space left on device). Made 28822 children.
---
 man2/clone.2 | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/man2/clone.2 b/man2/clone.2
index e4bee67bf..262815b01 100644
--- a/man2/clone.2
+++ b/man2/clone.2
@@ -1091,6 +1091,12 @@ Cannot allocate sufficient memory to allocate a task structure for the
 child, or to copy those parts of the caller's context that need to be
 copied.
 .TP
+.B ENOSPC
+the maximum number of PIDs,
+.IR /proc/sys/kernel/pid_max ,
+was reached; see
+.BR proc (5).
+.TP
 .BR ENOSPC " (since Linux 3.7)"
 .\" commit f2302505775fd13ba93f034206f1e2a587017929
 .B CLONE_NEWPID
-- 
2.17.1





[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux