]> code.ossystems Code Review - openembedded-core.git/commitdiff
oeqa/utils/httpserver: Rework to avoid hangs and improve logging
authorRichard Purdie <richard.purdie@linuxfoundation.org>
Fri, 16 Nov 2018 09:33:28 +0000 (09:33 +0000)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Mon, 25 Feb 2019 22:13:07 +0000 (22:13 +0000)
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>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
meta/lib/oeqa/runtime/cases/apt.py
meta/lib/oeqa/runtime/cases/dnf.py
meta/lib/oeqa/runtime/cases/opkg.py
meta/lib/oeqa/utils/httpserver.py

index 8d4dd35c578d190f79063c03bf323b76871e687e..793143f72cfcbcc932164d8a83588382a6329f45 100644 (file)
@@ -18,7 +18,7 @@ class AptRepoTest(AptTest):
     @classmethod
     def setUpClass(cls):
         service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_DEB'], 'all')
-        cls.repo_server = HTTPService(service_repo, cls.tc.target.server_ip)
+        cls.repo_server = HTTPService(service_repo, cls.tc.target.server_ip, logger=cls.tc.logger)
         cls.repo_server.start()
 
     @classmethod
index dd7affca0a904dd8f3ef675c55657fb3038833db..ef81a8cb7df6a44f6f41adc50ce554acad1b8ca1 100644 (file)
@@ -55,7 +55,7 @@ class DnfRepoTest(DnfTest):
     @classmethod
     def setUpClass(cls):
         cls.repo_server = HTTPService(os.path.join(cls.tc.td['WORKDIR'], 'oe-testimage-repo'),
-                                      cls.tc.target.server_ip)
+                                      cls.tc.target.server_ip, logger=cls.tc.logger)
         cls.repo_server.start()
 
     @classmethod
index 668c876a415a94968e2d671c47183ca64142ed4e..62421413cc61ad160ec56b4079c23370c8ed65ad 100644 (file)
@@ -18,7 +18,7 @@ class OpkgRepoTest(OpkgTest):
     @classmethod
     def setUp(cls):
         service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_IPK'], 'all')
-        cls.repo_server = HTTPService(service_repo, cls.tc.target.server_ip)
+        cls.repo_server = HTTPService(service_repo, cls.tc.target.server_ip, logger=cls.tc.logger)
         cls.repo_server.start()
 
     @classmethod
index 7d12331453a6684b893b82eaab2af8f87530b54b..a48d4994fd7982bf6db79267518f8d8854bfca0d 100644 (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))
+