Форум сайта python.su
Подскажите пожалуйста с чем может быть связано и как можно объяснить не стабильный перехват сигналов в следующем коде:
import time import signal import logging import os import sys import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import threading from tornado.options import define, options define("port", default=8888, help="run on the given port", type=int) class ProxyServer: def __init__(self): self.__app = None self.__server = None self.ioloop = tornado.ioloop.IOLoop.instance() def __call__(self): tornado.options.parse_command_line() self.__app = tornado.web.Application([ (r"/", MainHandler), ]) self.__server = tornado.httpserver.HTTPServer(self.__app) self.__server.listen(options.port) self.ioloop.start() def sig_handler(self, sig, frame): logging.warning('Caught signal: %s', sig) self.ioloop.add_callback(self.shutdown) def shutdown(self): logging.info('Stopping http server') self.__server.stop() logging.info('Will shutdown in %s seconds ...') self.ioloop.stop() logging.info('Shutdown') @staticmethod def stop(): pid = os.getpid() os.kill(pid, signal.SIGTERM) os.kill(pid, signal.SIGINT) class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") def main(): count = 0 while count != 5: proxy = ProxyServer() th = threading.Thread(target=proxy) th.start() signal.signal(signal.SIGTERM, proxy.sig_handler) signal.signal(signal.SIGINT, proxy.sig_handler) print("In main {}".format(count)) time.sleep(10) ProxyServer.stop() time.sleep(5) count += 1 #proxy.start() if __name__ == "__main__": main()
Exception in thread Thread-2: Traceback (most recent call last): File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner self.run() File "/usr/lib/python3.5/threading.py", line 862, in run self._target(*self._args, **self._kwargs) File "/home/leming/Documents/test_start_stop_proxy-server.py", line 30, in __call__ self.__server.listen(options.port) File "/home/leming/.local/lib/python3.5/site-packages/tornado/tcpserver.py", line 142, in listen sockets = bind_sockets(port, address=address) File "/home/leming/.local/lib/python3.5/site-packages/tornado/netutil.py", line 197, in bind_sockets sock.bind(sockaddr) OSError: [Errno 98] Address already in use
Офлайн
ActionNum
Но ведь вы же в цикле запускаете пять серверов на одном и том же порту. Так нельзя, если порт уже занят его нельзя использовать, пока существующий сервер его не освободит.
Офлайн
FishHookТак я же перед каждым очередным запуском останавливаю сервер и ioloop, жду некоторое время и потом заново стартую! Может я не понимю как работает python. И самое не понятное то, что этот небольшой тест остановки и запуска иногда проходит и отрабатывает чисто, когда все сигналы перехватываются и срабатывает вызов shutdown. Задача научиться стартовать и останавливать сервер освободив корректно порт.
ActionNumНо ведь вы же в цикле запускаете пять серверов на одном и том же порту. Так нельзя, если порт уже занят его нельзя использовать, пока существующий сервер его не освободит.
Офлайн
Всем Спасибо! Тему можно закрывать, проблема была не в перехвате сигналов, а в ожидании завершения работы прокси торнадовского сервера. Проблему помогла решить статья: http://tornadogists.com/4643396/
Исходный код теперь выглядит так:
import time import signal import logging import os import sys import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import threading from tornado.options import define, options define("port", default=8888, help="run on the given port", type=int) MAX_WAIT_SECONDS_BEFORE_SHUTDOWN = 3 class ProxyServer: def __init__(self): self.__app = None self.__server = None self.ioloop = tornado.ioloop.IOLoop.instance() def __call__(self): tornado.options.parse_command_line() self.__app = tornado.web.Application([ (r"/", MainHandler), ]) self.__server = tornado.httpserver.HTTPServer(self.__app, xheaders=True) self.__server.listen(options.port) self.ioloop.start() def sig_handler(self, sig, frame): logging.warning('Caught signal: %s', sig) self.ioloop.add_callback(self.shutdown) def shutdown(self): logging.info('Stopping http server') self.__server.stop() logging.info('Will shutdown in %s seconds ...', MAX_WAIT_SECONDS_BEFORE_SHUTDOWN) deadline = time.time() + MAX_WAIT_SECONDS_BEFORE_SHUTDOWN def stop_loop(): now = time.time() if now < deadline and (self.ioloop._callbacks or self.ioloop._timeouts): self.ioloop.add_timeout(now + 1, stop_loop) else: self.ioloop.stop() logging.info('Shutdown') stop_loop() @staticmethod def stop(): pid = os.getpid() os.kill(pid, signal.SIGTERM) os.kill(pid, signal.SIGINT) class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") def main(): count = 0 while count != 10: proxy = ProxyServer() th = threading.Thread(target=proxy) th.start() signal.signal(signal.SIGTERM, proxy.sig_handler) signal.signal(signal.SIGINT, proxy.sig_handler) print("In main {}".format(count)) time.sleep(10) ProxyServer.stop() time.sleep(5) count += 1 #proxy.start() if __name__ == "__main__": main()
Офлайн