mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-28 03:02:22 +02:00
fix: use socket.fromfd in send_batch_sync for Python 3.13 compat
Python 3.13's asyncio TransportSocket wrapper rejects setblocking(). Dup the underlying fd via socket.fromfd() into a plain socket that the executor thread can drive in blocking mode, then detach() after the batch to avoid closing the transport's fd.
This commit is contained in:
parent
f9f1a4d4d8
commit
46bad0b639
@ -20,6 +20,7 @@ import logging
|
|||||||
import asyncio
|
import asyncio
|
||||||
import threading
|
import threading
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
|
import socket as _socket
|
||||||
|
|
||||||
from gns3server.utils.asyncio import locking
|
from gns3server.utils.asyncio import locking
|
||||||
from .ubridge_error import UbridgeError
|
from .ubridge_error import UbridgeError
|
||||||
@ -296,10 +297,15 @@ class UBridgeHypervisor:
|
|||||||
transport = self._writer.transport
|
transport = self._writer.transport
|
||||||
if transport is None or transport.is_closing():
|
if transport is None or transport.is_closing():
|
||||||
raise UbridgeError("Transport closed")
|
raise UbridgeError("Transport closed")
|
||||||
sock = transport.get_extra_info("socket")
|
tr_sock = transport.get_extra_info("socket")
|
||||||
if sock is None:
|
if tr_sock is None:
|
||||||
raise UbridgeError("No underlying socket for sync send_batch")
|
raise UbridgeError("No underlying socket for sync send_batch")
|
||||||
|
|
||||||
|
# Python 3.13's transport socket wrapper (trsock) rejects
|
||||||
|
# setblocking(), so dup the underlying fd into a plain socket
|
||||||
|
# that the executor thread can drive in blocking mode.
|
||||||
|
sock = _socket.fromfd(tr_sock.fileno(), tr_sock.family, _socket.SOCK_STREAM)
|
||||||
|
|
||||||
# Serialise access to this hypervisor's socket — only one batch (sync
|
# Serialise access to this hypervisor's socket — only one batch (sync
|
||||||
# or async) talks to uBridge at a time. The node-level async lock
|
# or async) talks to uBridge at a time. The node-level async lock
|
||||||
# (:func:`_ubridge_send`) is held for the entire executor call, so no
|
# (:func:`_ubridge_send`) is held for the entire executor call, so no
|
||||||
@ -343,3 +349,4 @@ class UBridgeHypervisor:
|
|||||||
self._recv_buf = b""
|
self._recv_buf = b""
|
||||||
finally:
|
finally:
|
||||||
sock.setblocking(False)
|
sock.setblocking(False)
|
||||||
|
sock.detach() # release the dup'd fd, don't close transport
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user