Zeromq с питоном зависает при подключении к неверному сокету - PullRequest
2 голосов
/ 29 октября 2011

Если я подключаюсь к несуществующему сокету с pyzmq, мне нужно нажать CTRL_C, чтобы остановить программу. Может ли кто-нибудь объяснить, почему это происходит?

import zmq

INVALID_ADDR = 'ipc:///tmp/idontexist.socket'

context = zmq.Context()
socket = context.socket(zmq.REQ)

socket.connect(INVALID_ADDR)
socket.send('hello')

poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
conn = dict(poller.poll(1000))
if conn:
    if conn.get(socket) == zmq.POLLIN:
        print "got result: ", socket.recv(zmq.NOBLOCK)
else:
    print 'got no result'

Ответы [ 2 ]

8 голосов
/ 15 ноября 2011

Этот вопрос был также опубликован как выпуск pyzmq на GitHub. Я перефразирую свое объяснение здесь (я надеюсь, что это уместно, я довольно новичок в SO):

Общее правило: если есть сомнения, зависания в конце вашей программы zeromq происходят из-за LINGER.

Зависание здесь вызвано опцией сокета LINGER и происходит в методе context.term(), вызываемом во время сборки мусора в самом конце скрипта. Поведение LINGER описано в документации zeromq, но, проще говоря, это время ожидания (в миллисекундах) для ожидания любых ожидающих сообщений в очереди после закрытия сокета, прежде чем отбрасывать сообщения , Поведение по умолчанию - LINGER=-1, что означает ожидание вечно.

В этом случае, поскольку ни один узел не был запущен, сообщение «привет», которое вы пытались отправить, все еще ожидает в очереди отправки, когда сокет пытается закрыться. При LINGER=-1 ZeroMQ будет ждать, пока узел не будет готов принять это сообщение, прежде чем завершить работу. Если вы связываете сокет REP с 'ipc: ///tmp/idontexist.socket', когда этот скрипт, по-видимому, зависает, сообщение будет доставлено, и скрипт завершит корректный выход.

Если вы не хотите, чтобы ваш скрипт ждал (как указано в ваших инструкциях печати, которые вы уже отказались от получения ответа), задайте для LINGER любое неотрицательное значение (например, socket.linger = 0) и context.term() вернется после ожидания указанного количества миллисекунд.

Следует отметить, что имя переменной INVALID_ADDR предполагает понимание того, что подключение к интерфейсу, у которого еще нет прослушивателя, недопустимо - это неверно. zeromq позволяет событиям bind / connect происходить в любом порядке, как показано вышеописанным поведением привязки сокета REP к интерфейсу, в то время как скрипт отправки блокирует term().

0 голосов
/ 31 октября 2011

В большинстве случаев вы можете связывать и подключать сокеты ZMQ в любом порядке, так что ваш connect () / send () просто ожидает соответствующего bind () на другом конце, который никогда не приходит, поэтому программа выглядит похмелья. Проверьте, где программа висит, распечатав некоторые записи журнала ...

...