У меня есть очень простая реализация http.server.HTTPServer, которую я запускаю в Python 3.6. Я использую его для аутентификации OAuth2 по API Google Analytics. Как обычно, я создал простой дескриптор для получения ключа предоставления OAuth2 и использую метод serve_forever (). Тем не менее, поток, используемый для создания подачи навсегда, зависает, и кажется, что он застрял глубоко в реализации Python 3.6.
Интересно, я не думаю, что мой код вообще имеет значение в этом случае. Посмотрите на стек вызовов, о котором сообщают слушатели, которые я настроил для отладки:
service_action started
service_action complete
service_action started
service_action complete
service_action started
service_action complete
service_action started
service_action complete
"socketserver.BaseServer.serve_forever : self._handle_request_noblock()"
"socketserver.BaseServer._handle_request_noblock : self.get_request()"
"socketserver.BaseServer._handle_noblock_request : self.process_request()"
"socketserver.BaseServer.process_request : self.finish_request()"
"socketserver.BaseServer.finish_request : self.RequestHandlerClass(request, client_address, self) # request == <socket.socket fd=1828, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 57504)>, client_address == ('127.0.0.1', 57504), self == <MDGCoreLib.Utilities.HttpServer.Server.Server object at 0x0000026304E3FC88>"
"socketserver.BaseRequestHandler.__init__ : set self.client_address"
"socketserver.BaseRequestHandler.__init__ : set self.server"
"socketserver.BaseRequestHandler.__init__ : setup()"
"socketserver.StreamRequestHandler.setup : self.connection = self.request"
"socketserver.BaseRequestHandler.__init__ : self.handle()"
"server.BaseHttpRequestHandler.handle : self.close_connection = True"
"server.BaseHTTPServer.handle_one_request : self.raw_requestline = self.rfile.readline(65537)"
"socket.readinto : self._checkClosed()"
"socket.readinto : return self._sock.recv_into(b) #b == <memory at 0x0000026304E38C48>"
"server.BaseHTTPHandler.handle_one_request : if len(self.raw_requestline) > 65536"
"server.BaseHTTPHandler.handle_one_request : if not self.raw_requestline"
"server.BaseHTTPHandler.handle_one_request : if not self.parse_request()"
"server.BaseHTTPHandler.handle_one_request : if not hassattr(self, mname)"
#My handler runs
*"OAuthGrantRequestHandler : self.send_response"
127.0.0.1 - - [27/Aug/2018 14:35:16] "GET /?(REDACTED) HTTP/1.1" 200 -
Request handler completed*
#My handler finishes
Parent thread : joining Thread 2
"server.BaseHTTPHandler.handle_one_request : flushing wfile to socket finishing request"
"socketserver.BaseRequestHandler.__init__ : self.finish()"
"socketserver.StreamRequestHandler.finish : "
"socketserver.BaseServer.process_request : self.shutdown_request"
service_action started
service_action complete
"socketserver.BaseServer.serve_forever : self._handle_request_noblock()"
"socketserver.BaseServer._handle_request_noblock : self.get_request()"
"socketserver.BaseServer._handle_noblock_request : self.process_request()"
"socketserver.BaseServer.process_request : self.finish_request()"
"socketserver.BaseServer.finish_request : self.RequestHandlerClass(request, client_address, self) # request == <socket.socket fd=1840, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 57505)>, client_address == ('127.0.0.1', 57505), self == <MDGCoreLib.Utilities.HttpServer.Server.Server object at 0x0000026304E3FC88>"
"socketserver.BaseRequestHandler.__init__ : set self.client_address"
"socketserver.BaseRequestHandler.__init__ : set self.server"
"socketserver.BaseRequestHandler.__init__ : setup()"
"socketserver.StreamRequestHandler.setup : self.connection = self.request"
"socketserver.BaseRequestHandler.__init__ : self.handle()"
"server.BaseHttpRequestHandler.handle : self.close_connection = True"
"server.BaseHTTPServer.handle_one_request : self.raw_requestline = self.rfile.readline(65537)"
"socket.readinto : self._checkClosed()"
"socket.readinto : return self._sock.recv_into(b) #b == <memory at 0x0000026304E38C48>"
"server.BaseHTTPHandler.handle_one_request : if len(self.raw_requestline) > 65536"
"server.BaseHTTPHandler.handle_one_request : if not self.raw_requestline"
"server.BaseHTTPHandler.handle_one_request : if not self.parse_request()"
"server.BaseHTTPHandler.handle_one_request : if not hassattr(self, mname)"
#My Handler Runs
"OAuthGrantRequestHandler : self.send_response"
127.0.0.1 - - [27/Aug/2018 14:35:18] "GET /favicon.ico HTTP/1.1" 200 -
Request handler completed
#My Handler Finishes
"server.BaseHTTPHandler.handle_one_request : flushing wfile to socket finishing request"
"socketserver.BaseRequestHandler.__init__ : self.finish()"
"socketserver.StreamRequestHandler.finish : "
"socketserver.BaseServer.process_request : self.shutdown_request"
service_action started
service_action complete
"socketserver.BaseServer.serve_forever : self._handle_request_noblock()"
"socketserver.BaseServer._handle_request_noblock : self.get_request()"
"socketserver.BaseServer._handle_noblock_request : self.process_request()"
"socketserver.BaseServer.process_request : self.finish_request()"
"socketserver.BaseServer.finish_request : self.RequestHandlerClass(request, client_address, self) # request == <socket.socket fd=2008, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 57506)>, client_address == ('127.0.0.1', 57506), self == <MDGCoreLib.Utilities.HttpServer.Server.Server object at 0x0000026304E3FC88>"
"socketserver.BaseRequestHandler.__init__ : set self.client_address"
"socketserver.BaseRequestHandler.__init__ : set self.server"
"socketserver.BaseRequestHandler.__init__ : setup()"
"socketserver.StreamRequestHandler.setup : self.connection = self.request"
"socketserver.BaseRequestHandler.__init__ : self.handle()"
"server.BaseHttpRequestHandler.handle : self.close_connection = True"
"server.BaseHTTPServer.handle_one_request : self.raw_requestline = self.rfile.readline(65537)"
"socket.readinto : self._checkClosed()"
"socket.readinto : return self._sock.recv_into(b) #b == <memory at 0x0000026304E38C48>"
The program '[54321] Python @ tcp://localhost:55098/?legacyUnitTest' has exited with code -1 (0xffffffff).
Выше приведено все из потока, выполняющего метод serve_forever (), и вы можете видеть, что родительский поток ожидает соединения, где вывод читает Parent thread : joining Thread 2
. Мой обработчик, встречается и завершается дважды, когда вывод "OAuthGrantRequestHandler : self.send_response"
и
Request handler completed
: но затем никогда больше не вызывается, пока внутренняя библиотека Python не зависнет на socket.readinto : return self._sock.recv_into(b)
при попытке обработать последний запрос.
У кого-нибудь раньше было такое зависание Python, и есть ли вокруг него? Я как бы в растерянности, поскольку он зависает между циклами server_forever (), где встречается мой обработчик / код.
ОБНОВЛЕНИЕ 1
Таким образом, сравнивая трассировки fiddler с запросами в HTTPServer, я вижу, что есть только два HTTPRequest, но HTTPServer.serve_forever()
пытается прочитать третий запрос, который находится там, где он висит. Я также проверил (вы можете видеть это в выводе выше), что метод shutdown_request () и соответствующие методы вызываются для выключения сокета. Так почему же цикл serve_forever
продолжает проходить проверку ниже и вызывать self._handle_request_noblock (), если он не получил новый запрос:
ready = selector.select(poll_interval)
if ready:
self._handle_request_noblock()