Используйте дескриптор сигнала, чтобы выключить флеш-сервер - PullRequest
0 голосов
/ 20 ноября 2019

Я использую macOS Mojave и Python 3.7. В своей работе я хочу полностью отключить сервер flask-socketio из обработчика сигналов, который в моем коде определен как SignalHandler. Я заметил, что без обработчика сигнала сервер может быть полностью выключен с помощью Ctrl-C. Однако обработчик сигнала необходим для моей работы. Я искал в Интернете и не смог найти решение для отключения сервера в моем случае. К вашему сведению, я нашел решения для выключения сервера с помощью « вызова останова flash-socketio из функции обработчика HTTP или SocketIO » или «, корректно завершившего работу сервера gevent (pywsgi) ».

Пример кода приведен ниже:

import os
import threading
import signal
import requests

from flask import Flask, send_from_directory
from flask_socketio import SocketIO, Namespace
import eventlet


class WebsiteCreator(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        app = Flask(__name__, template_folder="templates",
                    static_folder="templates/static")

        app.config['SECRET_KEY'] = 'Secret!'
        socketio = SocketIO(app, engineio_logger=True, logger=True)

        # Create a URL route in our application for "/"
        @app.route('/')
        def test_page():
            """
            This function loads the homepage
            """
            return send_from_directory(
                os.path.join(app.root_path, 'templates'),
                "index1.html"
            )

        @app.route('/stop', methods=['POST'])
        def shutdown_server():
            """
            This function stops the flask-socketio server
            """
            print("Received request to shut down the server.")
            socketio.stop() #something wrong here, but don't know how to solve
            return "The server has been shut down."

        class MyCustomNamespace(Namespace):
            def on_connect(self):
                print("Client just connected")

            def on_disconnect(self):
                print("Client just left")

            def on_messages(self, data):
                print(f"\nReceived data from client: \n {data}\n")
                return data

        socketio.on_namespace(MyCustomNamespace('/channel_A'))

        try:
            eventlet.wsgi.server(
                eventlet.wrap_ssl(eventlet.listen(("localhost", 8080)),
                                  certfile='server.crt',
                                  keyfile='server.key',
                                  server_side=True), app)
        except Exception as e:
            print(f"Website is not established due to:\n{e}")


# Terminate code from shell
class SignalHandler(object):
    def __init__(self):
        pass

    def __call__(self, signum, frame):
        print("Shutting down the website.")

        # Begin 'something' here to shut down the server...
        shutdown_server = requests.post("https://localhost:8080/stop", data=None)
        print(f"Shut down the server feedback: {shutdown_server}")
        # 'Something' ends here

        print("The website has been shut down.")


if __name__ == '__main__':

    WebsiteCreator().start()

    # If the following part is not included, the server can be shut down using Ctrl-C
    handler = SignalHandler()
    signal.signal(signal.SIGINT, handler)

В коде я запускаю сервер flask-socketio в потоке. Я хочу выключить сервер, выполнив некоторые действия в SignalHandler.

Тем не менее, когда я вышел из системы с помощью Ctrl-C, возникли некоторые исключения:

^C
Shutting down the website.
(23066) accepted ('127.0.0.1', 49720)
Received request to shut down the server.
127.0.0.1 - - [22/Nov/2019 13:08:18] "POST /stop HTTP/1.1" 200 0 0.000365
wsgi exiting
Exception ignored in: <module 'threading' from '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py'>
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/threading.py", line 1308, in _shutdown
    lock.acquire()
  File "web_app.py", line 74, in __call__
    shutdown_server = requests.post("https://localhost:8080/stop", data=None)        
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 116, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 646, in send
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/hubs/kqueue.py", line 105, in wait
    readers.get(fileno, hub.noop).cb(fileno)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/greenthread.py", line 221, in main
    result = function(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 818, in process_request
    proto.__init__(conn_state, self)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 357, in __init__
    self.handle()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 390, in handle
    self.handle_one_request()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 419, in handle_one_request
    self.raw_requestline = self._read_request_line()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/wsgi.py", line 402, in _read_request_line
    return self.rfile.readline(self.server.url_length_limit)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 589, in readinto
    return self._sock.recv_into(b)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 241, in recv_into
    return self._base_recv(nbytes, flags, into=True, buffer_=buffer)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 256, in _base_recv
    read = self.read(nbytes, buffer_)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 176, in read
    super(GreenSSLSocket, self).read, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/eventlet/green/ssl.py", line 150, in _call_trampolining
    return func(*a, **kw)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 926, in read
    raise ValueError("Read on closed or unwrapped SSL socket.")
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 498, in send
ValueError: Read on closed or unwrapped SSL socket.
Removing descriptor: 8
142f38bdaaf34c7e8883e99a766fe310: Unexpected error "Read on closed or unwrapped SSL socket.", closing connection
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))

Пожалуйста, дайте мне несколько идей! Заранее спасибо.

...