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        # The signal handler from testimage.bbclass can cause deadlocks here
42        # if the HTTPServer is terminated before it can restore the standard
43        #signal behaviour
44        orig = signal.getsignal(signal.SIGTERM)
45        signal.signal(signal.SIGTERM, signal.SIG_DFL)
46        self.process.start()
47        signal.signal(signal.SIGTERM, orig)
48
49        if self.logger:
50            self.logger.info("Started HTTPService on %s:%s" % (self.host, self.port))
51
52
53    def stop(self):
54        if hasattr(self, "server"):
55            self.server.server_close()
56        if hasattr(self, "process"):
57            self.process.terminate()
58            self.process.join()
59        if self.logger:
60            self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port))
61
62