From bbc1a0d06b1bce3750935d1fd5787cca063be62c Mon Sep 17 00:00:00 2001 From: JRG Date: Fri, 14 Aug 2026 22:51:17 +0300 Subject: [PATCH] BackboneInterface: fix epoll RX starvation Speedtest.py fails when running on a shared instance with data_cap = 2*1024*1024*1024 Request both EPOLLIN | EPOLLOUT in tx_ready() and process both events in __job() Not included: Speedtest.py: change link.status == RNS.Link.ACTIVE to link.status != RNS.Link.CLOSED --- RNS/Interfaces/BackboneInterface.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/RNS/Interfaces/BackboneInterface.py b/RNS/Interfaces/BackboneInterface.py index 49601af4..799ac333 100644 --- a/RNS/Interfaces/BackboneInterface.py +++ b/RNS/Interfaces/BackboneInterface.py @@ -295,7 +295,7 @@ class BackboneInterface(Interface): if interface.socket: fileno = interface.socket.fileno() if fileno in BackboneInterface.spawned_interface_filenos: - try: BackboneInterface.epoll.modify(fileno, select.EPOLLOUT) + try: BackboneInterface.epoll.modify(fileno, select.EPOLLIN | select.EPOLLOUT) except Exception as e: if str(e).endswith("No such file or directory"): pass elif str(e).endswith("Bad file descriptor"): pass @@ -315,7 +315,8 @@ class BackboneInterface(Interface): if fileno in BackboneInterface.spawned_interface_filenos: spawned_interface = BackboneInterface.spawned_interface_filenos[fileno] client_socket = spawned_interface.socket - if client_socket and fileno == client_socket.fileno() and (event & select.EPOLLIN): + socket_valid = client_socket and fileno == client_socket.fileno() + if socket_valid and (event & select.EPOLLIN): try: received_bytes = client_socket.recv(spawned_interface.HW_MTU) except Exception as e: RNS.log(f"Error while reading from {spawned_interface}: {e}", RNS.LOG_PATHING) if RNS.sl(RNS.LOG_PATHING) else None @@ -336,8 +337,9 @@ class BackboneInterface(Interface): except Exception as e: RNS.log(f"Error while removing spawned interface from {pif}: {e}", RNS.LOG_ERROR) spawned_interface.receive(received_bytes) - - elif client_socket and fileno == client_socket.fileno() and (event & select.EPOLLOUT): + + socket_valid_after_read = socket_valid and fileno in BackboneInterface.spawned_interface_filenos + if socket_valid_after_read and (event & select.EPOLLOUT): try: written = client_socket.send(spawned_interface.transmit_buffer) except Exception as e: written = 0 @@ -374,7 +376,7 @@ class BackboneInterface(Interface): spawned_interface.txb += written if spawned_interface.parent_interface: spawned_interface.parent_interface.txb += written - elif client_socket and fileno == client_socket.fileno() and event & (select.EPOLLHUP): + elif socket_valid_after_read and event & (select.EPOLLHUP): BackboneInterface.deregister_fileno(fileno) try: if fileno in BackboneInterface.spawned_interface_filenos: BackboneInterface.spawned_interface_filenos.pop(fileno)