【问题标题】:RuntimeError: File descriptor 8 is used by transportRuntimeError:传输使用文件描述符 8
【发布时间】:2019-07-25 11:30:45
【问题描述】:

最小的演示示例:

import asyncio

async def main():
    c1_reader, c1_writer = await asyncio.open_connection(host='google.com', port=80)
    c1_socket = c1_writer.get_extra_info('socket')
    c1_socket.close()

    c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)

asyncio.run(main())

运行这个程序会报这个错误:

$ python3 asyncio_fd_used.py
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 469, in _sock_connect
    sock.connect(address)
BlockingIOError: [Errno 36] Operation now in progress

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "asyncio_fd_used.py", line 11, in <module>
    asyncio.run(main())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
    return future.result()
  File "asyncio_fd_used.py", line 9, in main
    c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 77, in open_connection
    lambda: protocol, host, port, **kwds)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 941, in create_connection
    await self.sock_connect(sock, address)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 463, in sock_connect
    self._sock_connect(fut, sock, address)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 477, in _sock_connect
    self.add_writer(fd, self._sock_connect_cb, fut, sock, address)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 333, in add_writer
    self._ensure_fd_no_transport(fd)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 244, in _ensure_fd_no_transport
    f'File descriptor {fd!r} is used by transport '
RuntimeError: File descriptor 8 is used by transport <_SelectorSocketTransport fd=8 read=polling write=<idle, bufsize=0>>

只是为了解释为什么我在做低级别的socket.close() 而不是异步级别的writer.close():我正在尝试一些代码来发送 RST 数据包。但我可以想象人们会打电话给socket.close() 的其他原因,甚至可能是无意的。

【问题讨论】:

    标签: python python-3.x network-programming python-asyncio


    【解决方案1】:

    问题是低级套接字已关闭,但 asyncio 不知道这一点并认为它仍然是打开的。出于某种原因(性能?)asyncio 记住了套接字文件描述符(fileno)。

    当一个新连接打开时,操作系统给它相同的文件描述符编号,并且 asyncio 开始恐慌,因为它具有与之前的连接相关联的完全相同的 fd 编号。

    解决方案:告诉 asyncio 套接字已关闭 :)

    import asyncio
    
    async def main():
        c1_reader, c1_writer = await asyncio.open_connection(host='google.com', port=80)
        c1_socket = c1_writer.get_extra_info('socket')
        c1_socket.close()
        c1_writer.close()  # <<< here
    
        c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)
    
    asyncio.run(main())
    

    此代码运行时不会引发错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多