diff options
author | jamiewalch <jamiewalch@chromium.org> | 2016-02-16 14:14:21 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-16 22:15:54 +0000 |
commit | 4dc4509a5cf240192dfeaafebf1986c0753814f7 (patch) | |
tree | 49ae512fd613a2310f134a4fab572745b226f717 /remoting/host | |
parent | 988e21478d74154034a0ba74db62f2f39064403e (diff) | |
download | chromium_src-4dc4509a5cf240192dfeaafebf1986c0753814f7.zip chromium_src-4dc4509a5cf240192dfeaafebf1986c0753814f7.tar.gz chromium_src-4dc4509a5cf240192dfeaafebf1986c0753814f7.tar.bz2 |
Add message from grandchild to parent to indicate successful host launch.
Previously, the grandparent process would assume the host started successfully
if the grandchild closed the pipe. However, this happens regardless of the
exit code of the grandchild process. This CL allows commands to be sent between
the processes in addition to log messages, and defines an explicit command to
indicate successful start-up; if the grandparent does not receive this command,
it indicates failure via a non-zero exit code.
BUG=332930
TEST=chmod -x remoting_me2me_host; linux_me2me_host.py --start; echo $? (should give 1)
Review URL: https://codereview.chromium.org/1685793003
Cr-Commit-Position: refs/heads/master@{#375680}
Diffstat (limited to 'remoting/host')
-rwxr-xr-x | remoting/host/linux/linux_me2me_host.py | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/remoting/host/linux/linux_me2me_host.py b/remoting/host/linux/linux_me2me_host.py index d2642ac..9c80e78 100755 --- a/remoting/host/linux/linux_me2me_host.py +++ b/remoting/host/linux/linux_me2me_host.py @@ -512,7 +512,7 @@ class Desktop: self.host_ready = True if (ParentProcessLogger.instance() and False not in [desktop.host_ready for desktop in g_desktops]): - ParentProcessLogger.instance().release_parent() + ParentProcessLogger.instance().release_parent(True) signal.signal(signal.SIGUSR1, sigusr1_handler) args.append("--signal-parent") @@ -682,29 +682,42 @@ class ParentProcessLogger(object): ParentProcessLogger.__instance = self def start_logging(self): - """Installs a logging handler that sends log entries to a pipe. + """Installs a logging handler that sends log entries to a pipe, prefixed + with the string 'MSG:'. This allows them to be distinguished by the parent + process from commands sent over the same pipe. Must be called by the child process. """ self._read_file.close() self._logging_handler = logging.StreamHandler(self._write_file) + self._logging_handler.setFormatter(logging.Formatter(fmt='MSG:%(message)s')) logging.getLogger().addHandler(self._logging_handler) - def release_parent(self): + def release_parent(self, success): """Uninstalls logging handler and closes the pipe, releasing the parent. Must be called by the child process. + + success: If true, write a "host ready" message to the parent process before + closing the pipe. """ if self._logging_handler: logging.getLogger().removeHandler(self._logging_handler) self._logging_handler = None if not self._write_file.closed: + if success: + self._write_file.write("READY\n") + self._write_file.flush() self._write_file.close() def wait_for_logs(self): """Waits and prints log lines from the daemon until the pipe is closed. Must be called by the parent process. + + Returns: + True if the host started and successfully registered with the directory; + false otherwise. """ # If Ctrl-C is pressed, inform the user that the daemon is still running. # This signal will cause the read loop below to stop with an EINTR IOError. @@ -718,25 +731,35 @@ class ParentProcessLogger(object): # Install a fallback timeout to release the parent process, in case the # daemon never responds (e.g. host crash-looping, daemon killed). # This signal will cause the read loop below to stop with an EINTR IOError. + # + # The value of 120s is chosen to match the heartbeat retry timeout in + # hearbeat_sender.cc. def sigalrm_handler(signum, frame): _ = signum, frame print("No response from daemon. It may have crashed, or may still be " "running in the background.", file=sys.stderr) signal.signal(signal.SIGALRM, sigalrm_handler) - signal.alarm(30) + signal.alarm(120) self._write_file.close() # Print lines as they're logged to the pipe until EOF is reached or readline # is interrupted by one of the signal handlers above. + host_ready = False try: for line in iter(self._read_file.readline, ''): - sys.stderr.write(line) + if line[:4] == "MSG:": + sys.stderr.write(line[4:]) + elif line == "READY\n": + host_ready = True + else: + sys.stderr.write("Unrecognized command: " + line) except IOError as e: if e.errno != errno.EINTR: raise print("Log file: %s" % os.environ[LOG_FILE_ENV_VAR], file=sys.stderr) + return host_ready @staticmethod def instance(): @@ -795,8 +818,10 @@ def daemonize(): os._exit(0) # pylint: disable=W0212 else: # Parent process - parent_logger.wait_for_logs() - os._exit(0) # pylint: disable=W0212 + if parent_logger.wait_for_logs(): + os._exit(0) # pylint: disable=W0212 + else: + os._exit(1) # pylint: disable=W0212 logging.info("Daemon process started in the background, logging to '%s'" % os.environ[LOG_FILE_ENV_VAR]) @@ -842,7 +867,7 @@ def cleanup(): g_desktops = [] if ParentProcessLogger.instance(): - ParentProcessLogger.instance().release_parent() + ParentProcessLogger.instance().release_parent(False) class SignalHandler: """Reload the config file on SIGHUP. Since we pass the configuration to the |