def _pidDied(self, pid, status, name=None): """ Called automatically from collectChildren, after a pid has been collected through waitpid(). If the pid is for a command, then we call status functions, commandCompleted and commandErrored, which can be overridden by plugins. """ if name is None: name = self._pids.get(pid, 'Unknown') self.info('Pid %s (%s) died' % (pid, name)) for command in list(self.commands): if pid == command.pid: self._foundResult = True command.commandDied(status) if command.isErrored(): self.info('%s (Pid %s) errored' % (name, pid)) f = command.getFailureReason() self.error(f) self.commandErrored(command.getCommandId(), f) else: self.info('%s (Pid %s) completed' % (name, pid)) self.commandCompleted(command.getCommandId()) if command.getChrootFactory(): self.chrootManager.chrootFinished( command.getChrootFactory().getRoot()) self.commands.remove(command) break server.Server._pidDied(self, pid, status, name)
def runCommand(self, commandClass, cfg, commandId, *args): """ Start the given command by instantiating the given class. Returns the command object that was created unless there was an error instantiating the command object, in which case None is returned. The function may also return False, which means that the command could not be run at this time (but did not error) If the command is forked, then the command object is appended the the list of running commands. """ command = None try: # errors before this point imply a problem w/ the node. # Below this point it is a problem w/ the command. command = commandClass(cfg, commandId, *args) if not command.isReady(): return False if command.shouldFork(): inF, outF = pipereader.makeMarshalPipes() pid = self._fork('Command %s' % command.getCommandId()) if not pid: try: self._resetSignalHandlers() inF.close() command.setWritePipe(outF) command.runCommandAndExit() finally: os._exit(1) else: command.pid = pid outF.close() command.setReadPipe(inF) self.commands.append(command) else: command.runCommandNoExit() self.commandCompleted(command.getCommandId()) except Exception, err: self.error( 'Command %s got exception: %s: %s' % (commandId, err.__class__.__name__, err)) tb = traceback.format_exc() self.commandErrored(commandId, str(err), tb) if command: command.commandErrored(str(err), tb)
def runCommand(self, commandClass, cfg, commandId, *args): """ Start the given command by instantiating the given class. Returns the command object that was created unless there was an error instantiating the command object, in which case None is returned. The function may also return False, which means that the command could not be run at this time (but did not error) If the command is forked, then the command object is appended the the list of running commands. """ command = None try: # errors before this point imply a problem w/ the node. # Below this point it is a problem w/ the command. command = commandClass(cfg, commandId, *args) if not command.isReady(): return False if command.shouldFork(): inF, outF = pipereader.makeMarshalPipes() pid = self._fork('Command %s' % command.getCommandId()) if not pid: try: self._resetSignalHandlers() inF.close() command.setWritePipe(outF) command.runCommandAndExit() finally: os._exit(1) else: command.pid = pid outF.close() command.setReadPipe(inF) self.commands.append(command) else: command.runCommandNoExit() self.commandCompleted(command.getCommandId()) except Exception, err: self.error('Command %s got exception: %s: %s' % (commandId, err.__class__.__name__, err)) tb = traceback.format_exc() self.commandErrored(commandId, str(err), tb) if command: command.commandErrored(str(err), tb)