fork:关闭所有打开的套接字

时间:2012-04-02 16:37:46

标签: python unix fork multiprocessing

我正在使用multiprocessing.Pool.map,它会分发当前流程。

我的理解是,默认情况下,所有文件描述符包括套接字在分叉时都会从主进程中复制。主进程本身是一个Web服务器(使用cherrypy),因此这会对开放端口等造成严重破坏。分叉进程实际上只在服务器正在使用的一个库中执行一些CPU-heavy numerical stuff - - 与网络/插座部分无关。

是否有一种简单的方法可以自动关闭新进程中的所有套接字?或者另一种避免分叉CherryPy服务器问题的方法?

使用CherryPy 3.2.2,Python 2.7;必须适用于Linux和OS X.

1 个答案:

答案 0 :(得分: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