I've seen cases where the result from str(sys.exc_info()[1]) is ""; this
breaks the error reporting as the parent relies on non-empty error
messages to properly detect child status (otherwise it will try to read
the pid and fail, so on).
While this was always in case of asserts, we need to ensure this doesn't
happen. Therefore we abstract this functionality (writing the error
message) and ensure we write a non-empty string in the new function.
---
lib/daemon.py | 3 +--
lib/utils.py | 21 ++++++++++++++++++---
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/lib/daemon.py b/lib/daemon.py
index 302097a..c3c4761 100644
--- a/lib/daemon.py
+++ b/lib/daemon.py
@@ -671,8 +671,7 @@ def GenericMain(daemon_name, optionparser,
prep_results = None
logging.info("%s daemon startup", daemon_name)
except Exception, err:
- if wpipe is not None:
- os.write(wpipe, _BeautifyError(err))
+ utils.WriteErrorToFD(wpipe, _BeautifyError(err))
raise
if wpipe is not None:
diff --git a/lib/utils.py b/lib/utils.py
index 54588cf..095e38b 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -435,9 +435,7 @@ def _StartDaemonChild(errpipe_read, errpipe_write,
except: # pylint: disable-msg=W0702
try:
# Report errors to original process
- buf = str(sys.exc_info()[1])
-
- RetryOnSignal(os.write, errpipe_write, buf)
+ WriteErrorToFD(errpipe_write, str(sys.exc_info()[1]))
except: # pylint: disable-msg=W0702
# Ignore errors in error handling
pass
@@ -445,6 +443,23 @@ def _StartDaemonChild(errpipe_read, errpipe_write,
os._exit(1) # pylint: disable-msg=W0212
+def WriteErrorToFD(fd, err):
+ """Possibly write an error message to a fd.
+
+ @type fd: None or int (file descriptor)
+ @param fd: if not None, the error will be written to this fd
+ @param err: string, the error message
+
+ """
+ if fd is None:
+ return
+
+ if not err:
+ err = "<unknown error>"
+
+ RetryOnSignal(os.write, fd, err)
+
+
def _RunCmdPipe(cmd, env, via_shell, cwd, interactive):
"""Run a command and return its output.
--
1.7.1