oeqa/utils/httpserver: Rework to avoid hangs and improve logging

testimage.bbclass installs a SIGTERM handler which conflicts with the
use of multiprocessing here. This is paritcularly problematic if the http
service is terminated before its started and hence before its had a chance
to reset the default signal handler (as the code was written).

Instead, temporarily remove testimage's handler whilst forking the http process
which means the correct handler is installed and won't deadlock.

Also take the opportunity to add in some log messages about the server start
and shutdown so that future debugging is easier and its clearer what the code
is doing.

(From OE-Core rev: cc0471439aa0085ca87deccf061c5b676ef12388)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie
2018-11-16 09:33:28 +00:00
parent 7692a65189
commit 1c88c939f8
4 changed files with 32 additions and 11 deletions

View File

@@ -1,13 +1,13 @@
import http.server
import multiprocessing
import os
import traceback
import signal
from socketserver import ThreadingMixIn
class HTTPServer(ThreadingMixIn, http.server.HTTPServer):
def server_start(self, root_dir):
import signal
signal.signal(signal.SIGTERM, signal.SIG_DFL)
def server_start(self, root_dir, logger):
os.chdir(root_dir)
self.serve_forever()
@@ -18,19 +18,40 @@ class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
class HTTPService(object):
def __init__(self, root_dir, host=''):
def __init__(self, root_dir, host='', logger=None):
self.root_dir = root_dir
self.host = host
self.port = 0
self.logger = logger
def start(self):
if not os.path.exists(self.root_dir):
self.logger.info("Not starting HTTPService for directory %s which doesn't exist" % (self.root_dir))
return
self.server = HTTPServer((self.host, self.port), HTTPRequestHandler)
if self.port == 0:
self.port = self.server.server_port
self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir])
self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir, self.logger])
# The signal handler from testimage.bbclass can cause deadlocks here
# if the HTTPServer is terminated before it can restore the standard
#signal behaviour
orig = signal.getsignal(signal.SIGTERM)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
self.process.start()
signal.signal(signal.SIGTERM, orig)
if self.logger:
self.logger.info("Started HTTPService on %s:%s" % (self.host, self.port))
def stop(self):
self.server.server_close()
self.process.terminate()
self.process.join()
if hasattr(self, "server"):
self.server.server_close()
if hasattr(self, "process"):
self.process.terminate()
self.process.join()
if self.logger:
self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port))