Module: check_mk
Branch: master
Commit: 3c6485cc3a86ce6218bfc168b8f8924558c9d2b6
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=3c6485cc3a86ce…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Jul 24 20:27:56 2018 +0200
Fixed background job standard FD handling
After each background job start these messages could be found in
the apache error log:
[Tue Jul 24 20:06:01.490903 2018] [wsgi:error] [pid 16596] [client
127.0.0.1:40244] close failed in file object destructor:
[Tue Jul 24 20:06:01.490960 2018] [wsgi:error] [pid 16596] [client
127.0.0.1:40244] IOError: [Errno 9] Bad file descriptor
This problem was caused by the handling of the open file descriptors
when starting background job.
During start all FDs except the first 3 were closed. The sys.stdout
object was replaced in python with a StringIO() wrapper which is
then used to collect the job results. But the FDs 0, 1 and 2 were
not closed.
To have a clean initial state we are now closing all FDs without
exception. We proceed without stdin and also replace stderr with a
stream wrapper that sends the written data to the var/log/web.log.
Change-Id: I3596a793ac37d406b0aeded15cb5f6df922cee0b
---
cmk/gui/background_job.py | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/cmk/gui/background_job.py b/cmk/gui/background_job.py
index 96ab9ac..2c6daf7 100644
--- a/cmk/gui/background_job.py
+++ b/cmk/gui/background_job.py
@@ -194,14 +194,17 @@ class BackgroundProcess(multiprocessing.Process):
except:
MAXFD = 256
- # Close all filedescriptors, except stdin/stdout
- os.closerange(3, MAXFD)
+ # Close all file descriptors
+ os.closerange(0, MAXFD)
def initialize_environment(self):
if not self._logger:
self._logger = cmk.log.logger
+ sys.stderr = StreamLogger(self._logger, cmk.log.ERROR)
+ sys.stdout = StringIO()
+
self._job_parameters["logger"] = self._logger
# Solely used for process identification
@@ -211,7 +214,6 @@ class BackgroundProcess(multiprocessing.Process):
def _execute_function(self):
# The specific function is called in a separate thread
# The main thread collects the stdout from the function-thread and updates the status file accordingly
- sys.stdout = StringIO()
t = threading.Thread(target=self._call_function_with_exception_handling, args=[self._job_parameters])
t.start()
@@ -260,6 +262,27 @@ class BackgroundProcess(multiprocessing.Process):
+# TODO(ab): Wouldn't it be better to also write the stderr to the job results instead of just writing
+# it to the web.log?
+class StreamLogger(object):
+ """File like stream object to redirects writes to the given logger"""
+ def __init__(self, logger, level):
+ super(StreamLogger, self).__init__()
+ self._logger = logger
+ self._level = level
+ self._linebuf = ''
+
+
+ def write(self, buf):
+ for line in buf.rstrip().splitlines():
+ self._logger.log(self._level, line.rstrip())
+
+
+ def flush(self):
+ pass
+
+
+
class BackgroundJobDefines(object):
base_dir = os.path.join(cmk.paths.var_dir, "background_jobs")
process_name = "cmk-job" # NOTE: keep this name short! psutil.Process tends to truncate long names