【问题标题】:Python Errno 9 Bad file descriptor in Mac OS XPython Errno 9 Mac OS X 中的错误文件描述符
【发布时间】:2023-11-30 07:26:01
【问题描述】:

我有以下代码在多次运行后没有任何问题 Linux 中的彼此:

def test_ftp(ftpserver):
    with FTP() as f:
        f.connect("localhost", port=ftpserver.server_port)
        f.login("M1", "bachmann")
        f.cwd("/")
        f.mkd("FOO")
        f.quit()

相同的测试只能在 MacOS X 中运行一次,之后它就会挂起。重新启动机器是我重新运行测试的唯一方法。

ftpserver 是在pytest-localftpserver 中定义的测试夹具,我在这里发布此夹具的代码是因为我怀疑它是错误的原因:

class MPFTPServer(multiprocessing.Process):

    def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
        self._server = SimpleFTPServer(username, password, ftp_home, ftp_port)
        self.server_home = self._server.ftp_home
        self.anon_root = self._server.anon_root
        self.server_port = self._server.ftp_port

        super().__init__(**kwargs)

    def run(self):
        self._server.serve_forever()

    def join(self):
        self._server.stop()

    def stop(self):
        self._server.stop()

@pytest.fixture(scope="session", autouse=True)
def ftpserver(request):
    """The returned ``ftpsever`` provides a threaded instance of
    ``pyftpdlib.servers.FTPServer`` running on localhost.
    ...
    """

    from pytest_localftpserver.plugin import MPFTPServer
    ftp_user = os.getenv("FTP_USER", "fakeusername")
    ftp_password = os.getenv("FTP_PASS", "qweqwe")
    ftp_home =  os.getenv("FTP_HOME", "")
    ftp_port = int(os.getenv("FTP_PORT", 0))
    server = MPFTPServer(ftp_user, ftp_password, ftp_home, ftp_port)
    # This is a must in order to clear used sockets
    server.daemon = True
    server.start()
    yield server
    server.join()

您能说出为什么这段代码在 Linux 中“重复工作”,而在 MacOSX 中却不行吗?

更新

进一步挖掘,我发现 ftp 服务器甚至无法启动,因此挂起。代码崩溃并显示以下消息:

    Process MPFTPServer-1:
    Traceback (most recent call last):
      File "/opt/pkg/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
        self.run()
      File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pytest_localftpserver/plugin.py", line 81, in run
        self._server.serve_forever()
      File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/servers.py", line 207, in serve_forever
        self.ioloop.loop(timeout, blocking)
      File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 348, in loop
        poll(soonest_timeout)
      File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 709, in poll
        timeout)
    OSError: [Errno 9] Bad file descriptor

【问题讨论】:

    标签: python macos multiprocessing tornado


    【解决方案1】:

    好的,显然bad file descriptor in Mac OS X 是已知的:

    如果您在分叉之前创建 IOLoop 并且 然后尝试在子进程中使用它。如果你要使用叉子, 您必须在创建单例 IOLoop 之前执行此操作。

    所以解决方案只是在run 方法中启动服务器实例,而不是在__init__

    class MPFTPServer(multiprocessing.Process):
    
        def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
            self.username = username
            self.password = password
            self.server_home = ftp_home
            self.server_port = ftp_port
    
            super().__init__(**kwargs)
    
        def run(self):
            self._server = SimpleFTPServer(self.username, self.password,
                                           self.server_home, self.server_port)
            self._server.serve_forever()
    

    【讨论】:

      最近更新 更多