2017-06-14 2 views
0

Je cherche une explication sur l'erreur que je reçois avec l'extrait suivant:appels à fork multiples provoquent BlockingIOError

#!/usr/bin/env python3 

import os, sys 

if __name__ == '__main__': 
    while True: 
     pid = os.fork() 
     if pid == 0: 
      sys.exit() 
     elif pid > 0: 
      pass 
      # os.waitpid(pid, 0) 
     else: 
      sys.exit() 

Cela engendrera de nombreux processus (processus qui sortent comme ils sont frayé).

Cela finira par provoquer une BlockingIOError montrant comme ceci:

Traceback (most recent call last): 
    File "./asd.py", line 7, in <module> 
    pid = os.fork() 
BlockingIOError: [Errno 35] Resource temporarily unavailable 

Mais lorsque l'appel est os.waitpid décommentée, tout semble bien.

Pourquoi cette erreur se produit et qu'est-ce que cet appel waitpid peut changer à ce sujet?

Répondre

1

C'est le même problème whenever fork dies this way; le message d'erreur est à quel point EAGAIN est convoyé à vous:

  1. Vous êtes de mémoire ou
  2. Vous avez atteint la limite de processus (par exemple RLIMIT_NPROC)

waitpid fixe parce qu'il recueille les processus de l'enfant zombie; jusqu'à ce que vous le fassiez, ces processus comptent pour le plafond (il doit les conserver afin que le parent puisse consulter les informations de terminaison).

Vous pouvez voir les différents codes d'erreur fork documentés sur its man page.

+0

Merci pour cette réponse très utile. J'ai un programme qui fait beaucoup d'appels 'fork' pour générer des processus qui peuvent expirer. Dans ce cas, les processus ont été simplement détruits par le processus parent avec os.kill (ce qui, d'après votre réponse, ne suffit pas). Si je comprends bien votre réponse, appelez 'waitpid()' pour les processus qui ont expiré aussi. Mais y a-t-il une fonction qui aurait pour but de "moissonner" ces processus sans récupérer les informations? (Puisque je n'en ai pas besoin parce que je sais comment le processus s'est terminé dans un tel cas). – vmonteco

+1

@vmonteco: Vous pouvez faire en sorte que le parent se désintègre globalement de la gestion des processus enfants en [définissant explicitement le gestionnaire 'SIGCHLD' sur' SIG_IGN'] (https://en.wikipedia.org/wiki/Zombie_process#Overview); Python fournit un accès aux paramètres du gestionnaire de signal dans le module 'signal'. Cela signifie que vous ne pouvez pas obtenir le statut de sortie d'un enfant qui a déjà quitté. Il existe aussi une solution double -fork + + setsid pour créer des processus démons qui ont un effet similaire (vous pouvez récolter l'enfant intermédiaire immédiatement, et le petit-enfant est détaché). – ShadowRanger

+0

J'ai vérifié votre commentaire et finalement waitpid() semble être la meilleure solution (j'ai encore besoin d'obtenir le statut de sortie d'autres processus, et mettre en place un processus petit-enfant semble inutilement compliqué). Yey votre lien m'a appris des choses, merci encore pour ça! – vmonteco