2012-04-02 39 views
4

我正在使用multiprocessing.Pool.map,這會分叉當前進程。fork:關閉所有打開的套接字

我的理解是,默認情況下,所有文件描述符包括套接字都是在分支時從主進程複製的。主進程本身是一個web服務器(使用cherrypy),所以這對開放端口等造成嚴重破壞。分叉進程實際上只在服務器正在使用的一個庫中執行一些CPU-heavy numerical stuff - 與web /插座部分。

是否有一種簡單的方法可以自動關閉新進程中的所有套接字?或者另一種避免分叉CherryPy服務器的方法?

使用CherryPy 3.2.2,Python 2.7;必須在Linux和OS X上工作。

+0

偷懶的方法是打開任何插座之前創建進程池。 – 2012-04-02 16:40:19

+0

不幸的是,我需要所有內存的「當前」快照,在'pool.map()'調用時間...只是不是套接字:) – user124114 2012-04-02 18:17:13

回答

4

POSIX不包含列出或關閉一系列文件描述符的明智方法。

所以我們必須遍歷整個範圍(比如從3到1023),一次關閉一個文件描述符。或者,如果我們有/ proc文件系統,我們可以讀取/ proc/self/fd中打開的文件描述符列表並關閉這些列表。這可能比關閉所有可能的文件描述符更快。

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()) 

在我的系統:

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