Skip to content

Commit ccf7768

Browse files
authored
Merge pull request #2083 from oz123/fix-unix-socket
Fix backdoor support for unix socket
2 parents cd9e22d + ddd769c commit ccf7768

3 files changed

Lines changed: 58 additions & 10 deletions

File tree

docs/changes/1769.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix using gevent's BackdoorServer with Unix sockets.

src/gevent/backdoor.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ def handle(self, conn, _address): # pylint: disable=method-hidden
164164
``locals`` dictionary. Previously they were shared in a
165165
potentially unsafe manner.
166166
"""
167-
conn.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, True) # pylint:disable=no-member
167+
try:
168+
conn.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, True)
169+
except OSError:
170+
pass
171+
168172
raw_file = conn.makefile(mode="r")
169173
getcurrent().stdin = _StdIn(conn, raw_file)
170174
getcurrent().stdout = _StdErr(conn, raw_file)

src/gevent/tests/test__backdoor.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
from __future__ import print_function
2-
from __future__ import absolute_import
1+
import os
2+
import tempfile
33

44
import gevent
5-
from gevent import socket
6-
from gevent import backdoor
7-
85
import gevent.testing as greentest
6+
from gevent import backdoor
7+
from gevent import socket
98
from gevent.testing.params import DEFAULT_BIND_ADDR_TUPLE
109
from gevent.testing.params import DEFAULT_CONNECT
1110

11+
1212
def read_until(conn, postfix):
1313
read = b''
1414
assert isinstance(postfix, bytes)
@@ -60,15 +60,25 @@ def tearDown(self):
6060
gevent.sleep() # let spawned greenlets die
6161
super(Test, self).tearDown()
6262

63+
def _server_listen_argument(self):
64+
return DEFAULT_BIND_ADDR_TUPLE
65+
6366
def _make_and_start_server(self, *args, **kwargs):
64-
server = backdoor.BackdoorServer(DEFAULT_BIND_ADDR_TUPLE, *args, **kwargs)
67+
server = backdoor.BackdoorServer(self._server_listen_argument(), *args, **kwargs)
6568
server.start()
6669
return server
6770

71+
def _connection_arguments(self, server):
72+
return ((DEFAULT_CONNECT, server.server_port),)
73+
74+
def _socket_arguments(self):
75+
return ()
76+
6877
def _create_connection(self, server):
69-
conn = SocketWithBanner()
70-
conn.connect((DEFAULT_CONNECT, server.server_port)) # pylint:disable=not-callable
78+
conn = SocketWithBanner(*self._socket_arguments())
79+
7180
try:
81+
conn.connect(*self._connection_arguments(server)) # pylint:disable=not-callable
7282
banner = self._wait_for_prompt(conn)
7383
except:
7484
conn.close()
@@ -139,7 +149,8 @@ def test_builtins(self):
139149
msg="locals() unusable: %s..." % response)
140150

141151
def test_switch_exc(self):
142-
from gevent.queue import Queue, Empty
152+
from gevent.queue import Empty
153+
from gevent.queue import Queue
143154

144155
def bad():
145156
q = Queue()
@@ -163,6 +174,38 @@ def bad():
163174
'switching out, then throwing in\nGot Empty\nswitching out\nswitched in\n>>> ',
164175
response)
165176

177+
@greentest.skipUnless(
178+
hasattr(socket, 'AF_UNIX'),
179+
"Needs AF_UNIX support"
180+
)
181+
class TestUnixSocket(Test):
182+
def setUp(self):
183+
super().setUp()
184+
# Create a temporary file for the Unix socket
185+
self.unix_socket_path = tempfile.mktemp()
186+
187+
def tearDown(self):
188+
# Clean up the Unix socket file
189+
if os.path.exists(self.unix_socket_path):
190+
os.unlink(self.unix_socket_path)
191+
super().tearDown()
192+
193+
def _server_listen_argument(self):
194+
# Use the Unix socket for the BackdoorServer
195+
listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
196+
try:
197+
listener.bind(self.unix_socket_path)
198+
listener.listen(socket.SOMAXCONN)
199+
except Exception as ex:
200+
listener.close()
201+
raise RuntimeError(f"Failed to bind Unix socket at {self.unix_socket_path}: {ex}")
202+
return listener
203+
204+
def _connection_arguments(self, server):
205+
return (self.unix_socket_path,)
206+
207+
def _socket_arguments(self):
208+
return (socket.AF_UNIX, socket.SOCK_STREAM)
166209

167210
if __name__ == '__main__':
168211
greentest.main() # pragma: testrunner-no-combine

0 commit comments

Comments
 (0)