web-dev-qa-db-fra.com

bash fork: réessayer: ressource temporairement indisponible

J'essaie d'exécuter un script shell qui créera un processus à l'aide d'un script shell. Je reçois une erreur temporairement indisponible sur la ressource. comment identifier quelle limite (mémoire/processus/nombre de fichiers) crée ce problème. Ci-dessous, mes résultats ulimit -a.

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 563959
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 10000000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
4
Viswanath

Dans le cas des commentaires, où vous utilisiez peu de mémoire par thread, vous atteigniez les limites du groupe de contrôle. Vous trouverez que la valeur par défaut se situe autour de 12288, mais la valeur est accessible en écriture:

$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.max
12288
$ echo 15000 | Sudo tee /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.max
15000
$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.max
15000

Et si j’utilise mon programme "quelle est la limite de threads" (trouvé ici ) pour vérifier, avant:

$ ./thread-limit
Creating threads ...
100 threads so far ...
200 threads so far ...
...
12100 threads so far ...
12200 threads so far ...
Failed with return code 11 creating thread 12281 (Resource temporarily unavailable).
Malloc worked, hmmm

et après:

$ ./thread-limit
Creating threads ...
100 threads so far ...
200 threads so far ...
300 threads so far ...
...
14700 threads so far ...
14800 threads so far ...
14900 threads so far ...
Failed with return code 11 creating thread 14993 (Resource temporarily unavailable).
Malloc worked, hmmm

Bien sûr, les chiffres ci-dessus ne sont pas exacts car l'utilisateur "doug" a quelques autres threads en cours d'exécution, tels que mes sessions SSH sur mon serveur. Vérifier avec:

$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.current
8

Programme utilisé:

/* compile with:   gcc -pthread -o thread-limit thread-limit.c */
/* originally from: http://www.volano.com/linuxnotes.html */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>

#define MAX_THREADS 100000
#define PTHREAD_STACK_MIN 1*1024*1024*1024
int i;

void run(void) {
  sleep(60 * 60);
}

int main(int argc, char *argv[]) {
  int rc = 0;
  pthread_t thread[MAX_THREADS];
  pthread_attr_t thread_attr;

  pthread_attr_init(&thread_attr);
  pthread_attr_setstacksize(&thread_attr, PTHREAD_STACK_MIN);

  printf("Creating threads ...\n");
  for (i = 0; i < MAX_THREADS && rc == 0; i++) {
    rc = pthread_create(&(thread[i]), &thread_attr, (void *) &run, NULL);
    if (rc == 0) {
      pthread_detach(thread[i]);
      if ((i + 1) % 100 == 0)
    printf("%i threads so far ...\n", i + 1);
    }
    else
    {
      printf("Failed with return code %i creating thread %i (%s).\n",
         rc, i + 1, strerror(rc));

      // can we allocate memory?
      char *block = NULL;
      block = malloc(65545);
      if(block == NULL)
        printf("Malloc failed too :( \n");
      else
        printf("Malloc worked, hmmm\n");
    }
  }
sleep(60*60); // ctrl+c to exit; makes it easier to see mem use
  exit(0);
}

Voir aussi ici

Maintenant, si vous avez assez de mémoire, la prochaine limite sera définie par le numéro PID maximum par défaut, 32768, mais est également accessible en écriture. Bien évidemment, pour avoir plus de 32 768 processus, tâches ou unités d'exécution simultanés, il faudra que leur PID soit supérieur:

$ cat /proc/sys/kernel/pid_max
32768
$ echo 80000 | Sudo tee /proc/sys/kernel/pid_max
80000
$ cat /proc/sys/kernel/pid_max
80000

Notez que c'est volontairement qu'un nombre supérieur à 2 ** 16 a été choisi, pour voir s'il était réellement autorisé. Et maintenant, définissez le nombre maximal de groupes de contrôle sur, par exemple, 70000:

$ echo 70000 | Sudo tee /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.max
70000
$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.max
70000

Et à ce stade, sachez que le programme mentionné ci-dessus semble avoir une limite d'environ 32 768 threads, même si des ressources sont toujours disponibles, et utilisez donc une autre méthode. Mon serveur de test avec 16 gigaoctets de mémoire semble épuiser une autre ressource d'environ 62 344 tâches, même s'il semble qu'il reste encore de la mémoire disponible.

$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.current
62344

haut:

top - 13:48:26 up 21:08,  4 users,  load average: 281.52, 134.90, 70.93
Tasks: 62535 total, 201 running, 62334 sleeping,   0 stopped,   0 zombie
%Cpu0  : 96.6 us,  2.4 sy,  0.0 ni,  1.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 95.7 us,  2.4 sy,  0.0 ni,  1.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 95.1 us,  3.1 sy,  0.0 ni,  1.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 93.5 us,  4.6 sy,  0.0 ni,  1.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu4  : 94.8 us,  3.4 sy,  0.0 ni,  1.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu5  : 95.5 us,  2.6 sy,  0.0 ni,  1.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu6  : 94.7 us,  3.5 sy,  0.0 ni,  1.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu7  : 93.8 us,  4.5 sy,  0.0 ni,  1.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 15999116 total,   758684 free, 10344908 used,  4895524 buff/cache
KiB Swap: 16472060 total, 16470396 free,     1664 used.  4031160 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
37884 doug      20   0  108052  68920   3104 R   5.7  0.4   1:23.08 top
24075 doug      20   0    4360    652    576 S   0.4  0.0   0:00.31 consume
26006 doug      20   0    4360    796    720 S   0.4  0.0   0:00.09 consume
30062 doug      20   0    4360    732    656 S   0.4  0.0   0:00.17 consume
21009 doug      20   0    4360    748    672 S   0.3  0.0   0:00.26 consume

Il semble que j'ai finalement atteint mes paramètres ulimit par défaut pour les processus utilisateur et le nombre de minuteries (signaux):

$ ulimit -i
62340
doug@s15:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 62340
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 32768
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 62340
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Si je lève ces limites, je peux aller à 69 000 sujets, ce qui est tout ce que j'ai demandé et pour autant que je vais prendre cette réponse:

$ cat /sys/fs/cgroup/pids/user.slice/user-1000.slice/pids.current
69011

haut:

top - 16:39:43 up 33 min,  3 users,  load average: 314.59, 181.48, 105.27
Tasks: 69205 total, 234 running, 68971 sleeping,   0 stopped,   0 zombie
%Cpu(s): 93.7 us,  5.5 sy,  0.0 ni,  0.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 15999004 total,  2659452 free, 11393940 used,  1945612 buff/cache
KiB Swap: 16472060 total, 16472060 free,        0 used.  2866316 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 4166 doug      20   0  115408  75956   3252 R   5.1  0.5   1:30.52 top
62667 doug      20   0   28916   1516   1320 R   3.7  0.0   0:01.14 ps
73184 doug      20   0    7196   4396   1600 S   0.9  0.0   0:09.95 try_stuff5
 2038 doug      20   0    4360    652    576 S   0.4  0.0   0:00.34 consume
 4594 doug      20   0    4360    652    580 S   0.4  0.0   0:00.14 consume
 5435 doug      20   0    4360    652    576 S   0.4  0.0   0:00.24 consume
 8891 doug      20   0    4360    688    612 S   0.4  0.0   0:00.14 consume

À un moment donné, vous aurez des problèmes, mais il est absolument incroyable de voir avec quelle élégance le système s'enlise. J'ai essayé 118000 threads et le système est complètement bloqué et j'ai eu beaucoup de ces erreurs:

Feb 17 16:13:02 s15 kernel: [  967.907305] INFO: task waiter:119371 blocked for more than 120 seconds.
Feb 17 16:13:02 s15 kernel: [  967.907335]       Not tainted 4.10.0-rc8-stock #194
Feb 17 16:13:02 s15 kernel: [  967.907357] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.

Et ma charge moyenne gonflée à ~ 29000. Mais je viens de quitter l'ordinateur pendant une heure et tout s'est réglé. J'ai décalé la rotation des threads de 200 microsecondes par rotation, puis j'ai pu exécuter très bien 118 000 threads (avec très peu de ressources utilisées par thread).

7
Doug Smythies