"""Stop all services and prepare to exit the process."""
- self.state = states.EXITING
- self.log('Bus EXITING')
- # This isn't strictly necessary, but it's better than seeing
- # "Waiting for child threads to terminate..." and then nothing.
+ self.state = states.EXITING
+ self.log('Bus EXITING')
+ # This isn't strictly necessary, but it's better than seeing
+ # "Waiting for child threads to terminate..." and then nothing.
+ # This method is often called asynchronously (whether thread,
+ # signal handler, console handler, or atexit handler), so we
+ # can't just let exceptions propagate out unhandled.
+ # Assume it's been logged and just die.
+ os._exit(70) # EX_SOFTWARE
"""Restart the process (may close connections).
def block(self, interval=0.1):
- """Wait for the EXITING state, KeyboardInterrupt or SystemExit."""
+ """Wait for the EXITING state, KeyboardInterrupt or SystemExit.
+ This function is intended to be called only by the main thread.
+ After waiting for the EXITING state, it also waits for all threads
+ to terminate, and then calls os.execv if self.execv is True. This
+ design allows another thread to call bus.restart, yet have the main
+ thread perform the actual execv call (required on some platforms).
except (KeyboardInterrupt, IOError):