Найти - Пользователи
Полная версия: Не стабильный перехват signal
Начало » Python для экспертов » Не стабильный перехват signal
1
ActionNum
Подскажите пожалуйста с чем может быть связано и как можно объяснить не стабильный перехват сигналов в следующем коде:
 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()

Получается когд не перехватывается signal, не срабатывает call_back на shutdown и порт остается занятым, получаем ошибку:
 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
FishHook
ActionNum
Но ведь вы же в цикле запускаете пять серверов на одном и том же порту. Так нельзя, если порт уже занят его нельзя использовать, пока существующий сервер его не освободит.
ActionNum
FishHook
ActionNumНо ведь вы же в цикле запускаете пять серверов на одном и том же порту. Так нельзя, если порт уже занят его нельзя использовать, пока существующий сервер его не освободит.
Так я же перед каждым очередным запуском останавливаю сервер и 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()
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB