codypiersall / pynng

Python bindings for Nanomsg Next Generation.
https://pynng.readthedocs.io
MIT License
260 stars 58 forks source link

pynng sock.recv() not interruptable #106

Open Sec42 opened 2 years ago

Sec42 commented 2 years ago

If I call .recv() on a socket created without recv_timeout, the call isn't interruptable with ^C.

Example:

with pynng.Sub0() as sock:
    sock.subscribe("")
    sock.dial(addr)
    msg = sock.recv()

Hangs indefinitely if I press ^C until a messages comes in.

ntakouris commented 1 year ago

You can work around this by adding a small timeout, inside a while loop, or while checking if some flag for shutdown is up (ex. to stop a thread)

with pynng.Sub0(...) as sock:
    sock.subscribe("")
    sock.dial(addr)
    while True: # or not stop_request
        try:
            msg = sock.recv(timeout=1.0)
        except pynng.exceptions.Timeout:
            pass 
codypiersall commented 1 year ago

This behavior cannot be fixed without changes to the underlying nng library; see an issue I opened a couple years ago for a discussion.

I'll leave this issue open just as a reference.

aqc-carlodri commented 1 year ago

I have tried your solution @ntakouris and it works, thank you. However, I had to abandon it because try-except statements in Python are very cheap (performance-wise) if there is no exception, but become expensive when the exception occurs. Since I had several IPC channels working together, I was adding a big performance burden on my code.

aqc-carlodri commented 1 year ago

I was playing around with pyzmq and stumbled into the same issue, and I found this SO reply that actually worked. Just sharing for now, haven't tried it with pynng. Will post back if it works.