Quantcast
Channel: Active questions tagged zeromq - Stack Overflow
Viewing all articles
Browse latest Browse all 193

Abort zeromq recv() or poll() from another thread - instantly and without the need to wait for timeout

$
0
0

I'm using ZeroMQ in Python and C++ in many configurations and I wonder which is the most elegant way to abort a recv() or poll() from another thread (e.g. in case of controlled program termination but also if you want to stop listening without the need to kill the socket).

In contrast to this question I don't just want to avoid infinitive wait but I want to return immediately from recv() or poll().

I know I can just provide a timeout and abort recv() like this:

poller = zmq.Poller()poller.register(socket, zmq.POLLIN)while _running:    if poller.poll(timeout=100) == []:        # maybe handle unwanted timout here..        continue    handle_message(socket.recv())

This will poll the socket endlessly until _running is set to False from another thread - after a maximum of 100 ms I'm done.

But this is not nice - I have a busy loop and it's hard this way to handle real timeouts which might be result of unwanted behavior. Also I have to wait for the timeout which is not critical in most cases but.. you know what I mean.

Of course I can poll an extra socket for abortion:

abort_socket = context.socket(zmq.SUB)abort_socket.setsockopt(zmq.SUBSCRIBE, b"")abort_socket.connect(<abort-publisher-endpoint>)poller = zmq.Poller()poller.register(socket, zmq.POLLIN)poller.register(abort_socket, zmq.POLLIN)while _running:    poll_result = poller.poll(timeout=1000)    if socket in poll_result:        handle_message(socket.recv())    elif abort_socket in poll_result:        break    else:        # handle real timeout here        pass

But this approach also has disadvantages:

  • it's a bit verbose - at the place where I trigger the abort I would have to create a publisher and use that to abort the receiver
  • the abort_socket can only be used from one thread, so I would have to make this sure

So my question is: how is this done the nice way?

Can I somehow just use something like Python's threading.Event or s.th. similar in other languages rather than the abort-socket which can be passed to the poller like this?:

def listener_thread_fn(event)    poller = zmq.Poller()    poller.register(socket, zmq.POLLIN)    poller.register(event, zmq.POLLIN)    while _running:        poll_result = poller.poll(timeout=1000)        if socket in poll_result:            handle_message(socket.recv())        elif event in poll_result:            break        else:            # handle real timeout here            pass

So you just had to create a theading.Event() in the first place, pass it to listener_thread_fn and call event.set() from any thread to abort.


Viewing all articles
Browse latest Browse all 193

Trending Articles