cobaltlazuli
cobaltlazuli

Reputation: 43

python script not terminating after timeout in ZMQ recv()

This is my first time working with IPC so far and I have written this script:

#!/usr/bin/python

import zmq

context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.setsockopt(zmq.RCVTIMEO, 2000)
socket.connect ("ipc:///tmp/something")
socket.send(b"123")
try:
    message = socket.recv()
except:
    print("DEBUG!")
    message = None

When my server script is running ( it simply sends an answer ) everything is working fine.

But when the .recv()-call timeouts ( e.g. because there is no server running ), the script won't terminate after the "DEBUG!"-print and I have to manually stop it using Ctrl+C.

I tried disconnecting and closing the socket, but it doesn't change anything.

When I put the whole script into a function and call it, I get the following error on KeyboardInterrupt:

^CException ignored in: <bound method Context.__del__ of <zmq.sugar.context.Context object at 0x7f16a36d5128>>
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/zmq/sugar/context.py", line 46, in __del__
    self.term()
  File "zmq/backend/cython/context.pyx", line 136, in zmq.backend.cython.context.Context.term (zmq/backend/cython/context.c:2339)
  File "zmq/backend/cython/checkrc.pxd", line 12, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/context.c:3207)
KeyboardInterrupt

I'm running Python 3.6.1 and version 16.0.2 of the PyZMQ module on an Arch Linux.

Upvotes: 4

Views: 4531

Answers (2)

colini
colini

Reputation: 776

user3666197's answer is correct, in the sense that socket.setsockopt(zmq.LINGER, 0) will solve the problem you described.

But per the docs the PAIR socket is only intended to be used for inter-thread communication in a single process. Specifically, it won't reconnect the connection is broken.

It may work correctly via ipc (I've never tried), but I recommend using a different socket type.

Upvotes: 0

user3666197
user3666197

Reputation: 1

May adopt this as a standard ZeroMQ infrastructure setup policy:

A default value of the LINGER attribute forces the socket instance to wait upon an attempt to .close(). So set this to 0 so as to avoid this feature / behaviour right upon instantiation, not to finally hang upon a termination.

import zmq
nIOthreads = 2                           # ____POLICY: set 2+: { 0: non-blocking, 1: blocking, 2: ...,  }
context = zmq.Context( nIOthreads )      # ____POLICY: set several IO-datapumps

socket  = context.socket( zmq.PAIR )
socket.setsockopt( zmq.LINGER,      0 )  # ____POLICY: set upon instantiations
socket.setsockopt( zmq.AFFINITY,    1 )  # ____POLICY: map upon IO-type thread
socket.setsockopt( zmq.RCVTIMEO, 2000 )

socket.connect( "ipc:///tmp/something" )
socket.send( b"123" )
try:
    message = socket.recv()
except:
    print( "DEBUG!" )
    message = None
finally:
    socket.close()                       # ____POLICY: graceful termination
    context.term()                       # ____POLICY: graceful termination

Upvotes: 5

Related Questions