2012-04-02 3 views
4

J'utilise multiprocessing.Pool.map, qui bifurque le processus en cours. Je comprends que, par défaut, tous les descripteurs de fichier , y compris les sockets, sont copiés à partir du processus maître lors de la mise en forme. Le processus maître lui-même est un serveur web (utilisant cherrypy), donc cela fait des ravages avec les ports ouverts, etc. Les processus forkés ne font vraiment que CPU-heavy numerical stuff dans l'une des bibliothèques que le serveur utilise - rien à voir avec le web/partie de douille.fork: ferme toutes les sockets ouvertes

Existe-t-il un moyen facile de fermer automatiquement toutes les sockets dans les nouveaux processus? Ou une autre façon d'éviter les problèmes de forking un serveur CherryPy?

En utilisant CherryPy 3.2.2, Python 2.7; doit fonctionner sous Linux et OS X.

+0

La manière paresseuse est de créer le pool de processus avant d'ouvrir des prises. –

+0

Malheureusement, j'ai besoin d'un instantané "courant" de toute la mémoire, à l'heure d'invocation de 'pool.map()' ... juste pas les sockets :) – user124114

Répondre

4

POSIX n'inclut pas un moyen sensé de lister ou de fermer une plage de descripteurs de fichiers. Nous devons donc boucler sur toute la gamme (de 3 à 1023), en fermant les descripteurs de fichiers un à la fois. Ou, si nous avons un système de fichiers/proc, nous pouvons lire la liste des descripteurs de fichiers ouverts dans/proc/self/fd et ne fermer que ceux-là. Cela peut être plus rapide que de fermer tous les descripteurs de fichiers possibles.

import os 

def close_files(fd_min=3, fd_max=-1): 
    if os.path.exists('/proc/self/fd'): 
     close_files_with_procfs(fd_min, fd_max) 
    else: 
     close_files_exhaustively(fd_min, fd_max) 

def close_files_exhaustively(fd_min=3, fd_max=-1): 
    import resource 
    fd_top = resource.getrlimit(resource.RLIMIT_NOFILE)[1] - 1 
    if fd_max == -1 or fd_max > fd_top: 
     fd_max = fd_top 
    for fd in range(fd_min, fd_max+1): 
     try: 
      os.close(fd) 
     except OSError: 
      pass 

def close_files_with_procfs(fd_min=3, fd_max=-1): 
    for nm in os.listdir("/proc/self/fd"): 
     if nm.startswith('.'): 
      continue 
     fd = int(nm) 
     if fd >= fd_min and (fd_max == -1 or fd < fd_max): 
      try: 
       os.close(fd) 
      except OSError: 
       pass 

def timereps(reps, func): 
    from time import time 
    start = time() 
    for i in range(0, reps): 
     func() 
    end = time() 
    return (end - start)/reps 

print "close_files: %f" % timereps(100, lambda: close_files()) 
print "close_files_exhaustively: %f" % timereps(100, lambda: close_files_exhaustively()) 
print "close_files_with_procfs: %f" % timereps(1000, lambda: close_files_with_procfs()) 

Sur mon système:

$ python ./close_fds.py 
close_files: 0.000094 
close_files_exhaustively: 0.010151 
close_files_with_procfs: 0.000039 
Questions connexes