Python sous-processus.Popen erroring avec OSError: [Errno 12] Ne peut pas allouer de la mémoire après la période de temps

Note: Cette question a été re-demandé un résumé de tous les débogage tentatives ici.


J'ai un script Python qui s'exécute comme un processus d'arrière-plan de l'exécution de toutes les 60 secondes. C'est en partie un appel à sous-processus.Popen pour obtenir la sortie de ps.

ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]

Au bout de quelques jours, l'appel est erroring avec:

Fichier "/home/admin/sd-agent/checks.py", à la ligne 436, dans getProcesses 
Le fichier "/usr/lib/python2.4/subprocess.py", à la ligne 533, dans __init__ 
Le fichier "/usr/lib/python2.4/subprocess.py" de ligne, 835, dans _get_handles 
OSError: [Errno 12] Impossible d'allouer de la mémoire 

Cependant la sortie de gratuit sur le serveur:

$ libres -m 
total free shared buffers cached 
Mem: 894 345 549 0 0 0 
-/+ buffers/cache: 345 549 
Swap: 0 0 0 

J'ai cherché partout pour le problème et trouvé cet article qui dit:

Solution est d'ajouter de l'espace de swap à votre serveur. Lorsque le noyau est un fork de commencer à le modeler ou de processus de découverte, il s'assure d'abord il y a assez d'espace disponible sur le swap de stocker le nouveau processus si nécessaire.

Je remarque qu'il n'y a pas de swap disponible à partir de la sortie ci-dessus. Est cela le problème et/ou ce que d'autres solutions pourrait-il être?

Mise à jour 13 Août 09 Le code ci-dessus est appelé toutes les 60 secondes dans le cadre d'une série de fonctions de surveillance. Le processus est automatiquement et que la vérification soit planifiée à l'aide sched. Le code correspondant à la fonction ci-dessus est:

def getProcesses(self):
    self.checksLogger.debug('getProcesses: start')

    # Memory logging (case 27152)
    if self.agentConfig['debugMode'] and sys.platform == 'linux2':
        mem = subprocess.Popen(['free', '-m'], stdout=subprocess.PIPE).communicate()[0]
        self.checksLogger.debug('getProcesses: memory before Popen - ' + str(mem))

    # Get output from ps
    try:
        self.checksLogger.debug('getProcesses: attempting Popen')

        ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]

    except Exception, e:
        import traceback
        self.checksLogger.error('getProcesses: exception = ' + traceback.format_exc())
        return False

    self.checksLogger.debug('getProcesses: Popen success, parsing')

    # Memory logging (case 27152)
    if self.agentConfig['debugMode'] and sys.platform == 'linux2':
        mem = subprocess.Popen(['free', '-m'], stdout=subprocess.PIPE).communicate()[0]
        self.checksLogger.debug('getProcesses: memory after Popen - ' + str(mem))

    # Split out each process
    processLines = ps.split('\n')

    del processLines[0] # Removes the headers
    processLines.pop() # Removes a trailing empty line

    processes = []

    self.checksLogger.debug('getProcesses: Popen success, parsing, looping')

    for line in processLines:
        line = line.split(None, 10)
        processes.append(line)

    self.checksLogger.debug('getProcesses: completed, returning')

    return processes

Cela fait partie d'une classe plus appelé vérifications qui est initialisé une fois lorsque le démon est lancé.

L'ensemble des contrôles de la classe peut être trouvé à http://github.com/dmytton/sd-agent/blob/82f5ff9203e54d2adeee8cfed704d09e3f00e8eb/checks.py avec le getProcesses fonction définie à partir de la ligne de 442. Ceci est appelé par doChecks (), commençant à la ligne 520.

Si vous exécutez haut, voyez-vous votre processus d'arrière-plan de consommer de plus grandes quantités de mémoire? Compte tenu de l'endroit du code où il est défaillant, je serais méfiant de l'exécution de descripteurs de fichiers (bien que ce doit être un autre errno). Ce que les autres sortes de choses faites-vous toutes les 60 secondes?
Après avoir connecté la sortie de free-m avant et après chaque Popen appel, la mémoire est rester le même. Comment puis-je vérifier les descripteurs de fichier? Divers autres processus sont en cours de lancement, mais elles sont également en cours de la session et de la mémoire n'est pas "utilisé" au fil du temps.
J'ai mis à jour ma réponse avec une autre suggestion.

OriginalL'auteur DavidM | 2009-08-01