aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2018-11-16 09:33:28 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-02-25 22:13:07 +0000
commit4eac9a5337d93b6cbd3916af97f62bb04881c9cd (patch)
tree524557eb3615860ffa1ec93d1efff4e4ac91abd8
parenta80498e62898110e2ed6b01cbb9f5dd85995d13b (diff)
downloadopenembedded-core-4eac9a5337d93b6cbd3916af97f62bb04881c9cd.tar.gz
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> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--meta/lib/oeqa/runtime/cases/apt.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/dnf.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/opkg.py2
-rw-r--r--meta/lib/oeqa/utils/httpserver.py37
4 files changed, 32 insertions, 11 deletions
diff --git a/meta/lib/oeqa/runtime/cases/apt.py b/meta/lib/oeqa/runtime/cases/apt.py
index 8d4dd35c57..793143f72c 100644
--- a/meta/lib/oeqa/runtime/cases/apt.py
+++ b/meta/lib/oeqa/runtime/cases/apt.py
@@ -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
diff --git a/meta/lib/oeqa/runtime/cases/dnf.py b/meta/lib/oeqa/runtime/cases/dnf.py
index dd7affca0a..ef81a8cb7d 100644
--- a/meta/lib/oeqa/runtime/cases/dnf.py
+++ b/meta/lib/oeqa/runtime/cases/dnf.py
@@ -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
diff --git a/meta/lib/oeqa/runtime/cases/opkg.py b/meta/lib/oeqa/runtime/cases/opkg.py
index 668c876a41..62421413cc 100644
--- a/meta/lib/oeqa/runtime/cases/opkg.py
+++ b/meta/lib/oeqa/runtime/cases/opkg.py
@@ -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
diff --git a/meta/lib/oeqa/utils/httpserver.py b/meta/lib/oeqa/utils/httpserver.py
index 7d12331453..a48d4994fd 100644
--- a/meta/lib/oeqa/utils/httpserver.py
+++ b/meta/lib/oeqa/utils/httpserver.py
@@ -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))
+