1# 2# SPDX-License-Identifier: MIT 3# 4 5import http.server 6import multiprocessing 7import os 8import traceback 9import signal 10from socketserver import ThreadingMixIn 11 12class HTTPServer(ThreadingMixIn, http.server.HTTPServer): 13 14 def server_start(self, root_dir, logger): 15 os.chdir(root_dir) 16 self.serve_forever() 17 18class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler): 19 20 def log_message(self, format_str, *args): 21 pass 22 23class HTTPService(object): 24 25 def __init__(self, root_dir, host='', port=0, logger=None): 26 self.root_dir = root_dir 27 self.host = host 28 self.port = port 29 self.logger = logger 30 31 def start(self): 32 if not os.path.exists(self.root_dir): 33 self.logger.info("Not starting HTTPService for directory %s which doesn't exist" % (self.root_dir)) 34 return 35 36 self.server = HTTPServer((self.host, self.port), HTTPRequestHandler) 37 if self.port == 0: 38 self.port = self.server.server_port 39 self.process = multiprocessing.Process(target=self.server.server_start, args=[self.root_dir, self.logger]) 40 41 def handle_error(self, request, client_address): 42 import traceback 43 exception = traceback.format_exc() 44 self.logger.warn("Exception when handling %s: %s" % (request, exception)) 45 self.server.handle_error = handle_error 46 47 # The signal handler from testimage.bbclass can cause deadlocks here 48 # if the HTTPServer is terminated before it can restore the standard 49 #signal behaviour 50 orig = signal.getsignal(signal.SIGTERM) 51 signal.signal(signal.SIGTERM, signal.SIG_DFL) 52 self.process.start() 53 signal.signal(signal.SIGTERM, orig) 54 55 if self.logger: 56 self.logger.info("Started HTTPService on %s:%s" % (self.host, self.port)) 57 58 59 def stop(self): 60 if hasattr(self, "server"): 61 self.server.server_close() 62 if hasattr(self, "process"): 63 self.process.terminate() 64 self.process.join() 65 if self.logger: 66 self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port)) 67 68