I am having trouble with basic Sockets.
Given the empty comment, I'm guessing this has been resolved or was a mistake. Closing, but feel free to comment if you want it reopened.
The nursery freezes up when the connections drop, then the client reconnects and the nursery is frozen, so I have to hit CTRL+C and instead of closing the program it closes the nursery and resumes where it should.
Issues with Cancel Scopes: If a nursery injects a Cancelled exception even when none of the tasks have received a Cancelled, it might cause the nursery to freeze1.
I think this may be the problem, perhaps.
I hope to overcome this problem with await trio.lowlevel.checkpoint() but all I can do is wait for it to freeze again -- if it will.
Could you provide a minimal reproducer program that has this problem (even if not frequently or under high load?)
async def proxy_make_irc_connection(client_socket: trio.SocketStream
| trio.SSLStream, ss_hostname: str, port: int) -> None:
"""Make a connection to the IRC network and fail (502) if unable to connect.
vars:
:type server: str
:@param client_socket: the client socket
:@param server: a string of the server to connect to
:@param port: the port number to connect to (integer)
:@return: returns None
"""
ss_hostname = ss_hostname.lower()
server_socket: trio.SSLStream | trio.SocketStream
server_socket_nossl: trio.SocketStream
try:
granted: bytes = b"HTTP/1.0 200 connection started with irc server.\r\n\r\n"
if not await socket_data.raw_send(client_socket, None, granted):
return None
except (trio.ClosedResourceError, trio.TrioInternalError, trio.BrokenResourceError,
trio.BusyResourceError, gaierror, OSError):
return None
try:
if port in (6697, 9999, 443, 6699, 6999, 7070) \
or (port == 7000 and fnmatch(ss_hostname, '*.dal.net') == False) \
and False == fnmatch(ss_hostname, '*.undernet.org'):
ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ssl_context.maximum_version = ssl.TLSVersion.TLSv1_3
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
try:
server_socket: trio.SocketStream | trio.SSLStream = await trio.open_ssl_over_tcp_stream(
ss_hostname,
port,
https_compatible=False,
ssl_context=ssl_context,
happy_eyeballs_delay=0.180)
except (trio.ClosedResourceError, trio.TrioInternalError, trio.BrokenResourceError,
trio.BusyResourceError, gaierror, OSError, trio.NoHandshakeError,
ConnectionRefusedError, ConnectionResetError, ConnectionAbortedError,
ConnectionError, BaseException):
try:
with trio.fail_after(17.8):
await socket_data.raw_send(client_socket, None,
b"HTTP/1.0 502 Unable to connect to remote host.\r\n\r\n")
await aclose_sockets(client_socket)
except (trio.TooSlowError, trio.ClosedResourceError, trio.TrioInternalError, trio.BrokenResourceError,
trio.BusyResourceError, gaierror, OSError, trio.NoHandshakeError,
ConnectionRefusedError, ConnectionResetError, ConnectionAbortedError,
ConnectionError, BaseException):
return None
else:
try:
server_socket: trio.SocketStream | trio.SSLStream = \
await trio.open_tcp_stream(ss_hostname, port, happy_eyeballs_delay=0.180)
except (trio.ClosedResourceError, trio.TrioInternalError, trio.BrokenResourceError,
trio.BusyResourceError, gaierror, OSError, trio.NoHandshakeError,
ConnectionRefusedError, ConnectionResetError, ConnectionAbortedError,
ConnectionError, BaseException):
try:
await socket_data.raw_send(client_socket, None,
b"HTTP/1.0 502 Unable to connect to remote host.\r\n\r\n")
await aclose_sockets(client_socket)
except (trio.ClosedResourceError, trio.TrioInternalError, trio.BrokenResourceError,
trio.BusyResourceError, gaierror, OSError, trio.NoHandshakeError,
ConnectionRefusedError, ConnectionResetError, ConnectionAbortedError,
ConnectionError, BaseException):
return None
await trio.sleep(0.280)
socket_data.create_data(client_socket, server_socket)
socket_data.hostname[server_socket] = ss_hostname + ':' + str(port)
async with trio.open_nursery() as nursery:
# Server_socket marked by 'ss' as the last parameter, writes to cs
nursery.start_soon(socket_received_chunk, client_socket, server_socket, 'ss')
# client_socket marked by 'cs' as the last parameter, writes to ss
nursery.start_soon(socket_received_chunk, client_socket, server_socket, 'cs')
# Write to client
nursery.start_soon(write_loop, client_socket, server_socket, socket_data.send_buffer[client_socket], 'cs')
# Write to server
nursery.start_soon(write_loop, client_socket, server_socket, socket_data.send_buffer[server_socket], 'ss')
except (EndSession,):
await aclose_both(client_socket)
return
except (BaseException) as exx:
print('BaseException #001A')
await aclose_both(client_socket)
return
finally:
# proxy_make_irc_connection()
print("connections were closed. nursery finished.")
I think I had some misaligned code that wasn't raising exceptions and a loop with aclose_both() eecuting a quit statement then closing the socket again creating a loop.
Gah sorry I forgot about this; unfortunately I don't really have the motivation right now to figure out the right context to call the function.
Uh, do you have logs from when you reproduced this? Also, the amount of except BaseException is scaring me because I feel like that'll catch a KeyboardInterrupt and it doesn't look like you're reraising!
Thank you for your KeyboardInterrupt tip. I had some problems where I could not seem to stop the program back to the prompt. This is probably why. Maybe not in this code but in all my code where I catch BaseException
Yea I would suggest not catching so many of the exceptions, for example TrioInternalError as far as I remember doesn't happen normally and when something raises that it can be quite bad and is worth knowing about