Skip to content

BUG: recv on DISH ignores signals until a message is received #2174

@jbdyn

Description

@jbdyn

I wrote this

  • I wrote this Issue and it does not include any output from an AI/LLM tool.

This is a pyzmq bug

  • This is a pyzmq-specific bug, not an issue of zmq socket behavior. Don't worry if you're not sure! We'll figure it out together.

What pyzmq version?

27.1.0

What libzmq version?

4.3.5

Python version (and how it was installed)

Python 3.14.3, via pacman

OS

Linux 6.18.18-1-MANJARO

What happened?

The recv and recv_multipart methods for a DISH socket seem to postpone signal handlers until a message is received.
This behaviour differs from the other sockets (have not tested GATHER, SCATTER, DGRAM, PEER and CHANNEL yet), where appropriate signal handlers abort a blocking recv or recv_multipart.

Compare radio.py and dish.py versus the non-draft counterparts pub.py and sub.py:

radio.py
from zmq import Context, RADIO, Frame
from time import sleep

ctx = Context()
socket = ctx.socket(RADIO)
socket.bind("tcp://localhost:5555")

frame = Frame(b"foo")
frame.group = "random"

while True:
    print("sending ...")

    socket.send(frame, copy=False)

    print("sent", frame)

    sleep(1)
dish.py
from zmq import Context, DISH

ctx = Context()
socket = ctx.socket(DISH)
socket.connect("tcp://localhost:5555")

socket.join("random")

while True:
    print("waiting ...")

    frame = socket.recv(copy=False)

    assert frame.group == "random"

    print("received", frame)
pub.py
from zmq import Context, PUB
from time import sleep

ctx = Context()
socket = ctx.socket(PUB)
socket.bind("tcp://localhost:5555")

frames = [b"random", b"foo"]

while True:
    print("sending ...")

    socket.send_multipart(frames, copy=False)

    print("sent", frames)

    sleep(1)
sub.py
from zmq import Context, SUB

ctx = Context()
socket = ctx.socket(SUB)
socket.connect("tcp://localhost:5555")

socket.subscribe("random")

while True:
    print("waiting ...")

    frames = socket.recv_multipart(copy=False)

    print("received", frames)

Run dish.py or sub.py and try to interrupt with Ctrl-C.
dish.py does nothing and continues to run, sub.py prints the traceback of a KeyboardInterrupt and exits.

In case of dish.py, after a Ctrl-C has been hit on it, run radio.py and watch dish.py behave like sub.py but only after is has received a message from radio.py.

More info

The current workaround is to wait for incoming data on the DISH socket via zmq.select or Poller.poll and then call recv or recv_multipart, which then won't block. Both select and Poller.poll don't postpone a signal handler.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions