2014-01-15 2 views
2

У меня есть еще немного кода, чем это, поэтому я обрезаю его до того, что кажется уместным. За документированной, например, у меня есть класс питона для ZeroRPC использовать:Исключения для сервера peroon ZeroRPC при попытке остановить или закрыть

import zerorpc, sys, signal 

class MyClass: 
    pass 

zpc = 0 
if __name == '__main__': 
    zpc = zerorpc.Server(MyClass) 
    zpc.bind('ipc://./mysocket.sock') 
    zpc.run() 
    print("zpc stopped"); sys.stdout.flush() 

Сценарий питон порождены как ChildProcess от моего сервера Node.js, который прослушивает на стандартный вывод и стандартный поток ошибок. Когда время соединения клиента заканчивается или сервер выключается, я вызываю kill() в ChildProcess, который отправляет ему SIGTERM.

С помощью только что приведенного выше кода, «zpc stopped» никогда не попадает в обратный вызов Node.js, что указывает на то, что сервер ZeroRPC будет убит где-то в своем запуске. Кроме того, файл сокета все еще существует, показывая, что сервер также не закрывает сокет. Поэтому я полагал, что я бы назвал остановку() или близко() на сервере после захвата SIGTERM:

def sig_handle (signal, frame): 
    global zpc 
    print("SIGTERM received.") # <-- this does occur 
    zpc.stop() # <-- Exception thrown here and at run() 
    sys.exit(0) 

signal.signal(signal.SIGTERM, sig_handle) 

Исключения подхвачена Node.js через Stderr обратного вызова:

Gateway Error: File "/usr/lib/python2.6/site-packages/zerorpc/core.py", line 178, in stop 

Gateway Error:  self._acceptor_task.kill() 
    File "/usr/lib64/python2.6/site-packages/gevent/greenlet.py", line 235, in kill 

Gateway Error:  waiter.get() 
    File "/usr/lib64/python2.6/site-packages/gevent/hub.py", line 568, in get 

Gateway Error:  return self.hub.switch() 
    File "/usr/lib64/python2.6/site-packages/gevent/hub.py", line 330, in switch 
    switch_out() 
    File "/usr/lib64/python2.6/site-packages/gevent/hub.py", line 334, in switch_out 
    raise AssertionError('Impossible to call blocking function in the event loop callback') 
AssertionError: Impossible to call blocking function in the event loop callback 

Gateway Error: Traceback (most recent call last): 
    File "gateway.py", line 111, in <module> 
    zpc.run() 

Gateway Error: File "/usr/lib/python2.6/site-packages/zerorpc/core.py", line 171, in run 
    self._acceptor_task.get() 
    File "/usr/lib64/python2.6/site-packages/gevent/greenlet.py", line 258, in get 

Gateway Error:  result = self.parent.switch() 
    File "/usr/lib64/python2.6/site-packages/gevent/hub.py", line 331, in switch 

Gateway Error:  return greenlet.switch(self) 
AssertionError: Impossible to call blocking function in the event loop callback 

Изменение остановки() для закрытия() приводит к тому же самому окончательному набору исключений. Внедряя ту же идею в Javascript (Node.js), close() очищает запущенный сервер (и его файл сокета в каталоге), не выдавая никаких исключений или предупреждений.

Все это оставляет мне вопрос: как очистить сервер ZeroRPC в Python, если не остановить() или закрыть()?

ответ

6

Используйте gevent.signal(), чтобы установить обработчик сигнала вместо signal.signal().

Это связано с тем, что стандартный сигнал модуля непосредственно отображает UNIX API, который запускает обработчик сигнала вне gentent eventloop без какой-либо концепции gevent greenlet/coroutine. gevent.signal интегрирован с gevent ioloop, и убедитесь, что вы выполняете обработчик вашего сигнала в своей собственной greenlet, в eventloop.

GEvent решение совместимо:

import zerorpc, sys, gevent, signal, os 

class MyClass: 
     pass 

if __name__ == '__main__': 
    zpc = zerorpc.Server(MyClass) 
    zpc.bind('ipc://./mysocket.sock') 
    gevent.signal(signal.SIGTERM, zpc.stop) 
    zpc.run() 
    print("zpc stopped"); sys.stdout.flush() 
+0

Потрясающе, что работал отлично. Я пошел вперед и бросил zpc.close() после zpc.run(), чтобы убедиться, что сокет также очищается от системы. Благодаря! – Thomas

+0

Вам не нужно добавлять .close() после .run()! Когда .run() возвращается, сервер zerorpc корректно и чисто остановлен. См. Более подробное объяснение здесь: http://stackoverflow.com/questions/19208535/how-to-run-zerorpc-as-a-greenlet – bombela

+1

Чтобы уточнить, что я имею в виду под «очищенным» - это unix-сокет, который остается в путь, если я остановлю только() сервер. Вызов метода close() удаляет этот артефакт. – Thomas

 Смежные вопросы

  • Нет связанных вопросов^_^