def wait_execute(proc, exit_on_error, capture_output=True, print_output=True, timeout=None, stdout_transformer=None, stderr_transformer=None, read_buffer_length=DEFAULT_READ_BUFFER_LENGTH): """Looks after a command as it runs, and prints/returns its output after.""" if stdout_transformer is None: stdout_transformer = output_transformer.Hidden() if stderr_transformer is None: stderr_transformer = output_transformer.Identity() logger.debug('---------------------------------------') wait_timeout(proc, timeout) output_chunks = [] stdout_transformer.set_output(sys.stdout) stderr_transformer.set_output(sys.stderr) # Stdout is printed as the process runs because some commands (e.g. ninja) # might take a long time to run. for chunk in iter(lambda: proc.stdout.read(read_buffer_length), b''): if print_output: local_logging.send_output(chunk) stdout_transformer.process(chunk) if capture_output: # According to: http://stackoverflow.com/questions/19926089, this is the # fastest way to build strings. output_chunks.append(chunk) # We cannot read from stderr because it might cause a hang. # Therefore, we use communicate() to get stderr instead. # See: https://github.com/google/clusterfuzz-tools/issues/278 stdout_data, stderr_data = proc.communicate() stdout_data = stdout_data or '' stderr_data = stderr_data or '' kill(proc) for (transformer, data) in [(stdout_transformer, stdout_data), (stderr_transformer, stderr_data)]: if capture_output: output_chunks.append(data) if print_output: local_logging.send_output(data) transformer.process(data) transformer.flush() logger.debug('---------------------------------------') if proc.returncode != 0: logger.debug('| Return code is non-zero (%d).', proc.returncode) if exit_on_error: logger.debug('| Exit.') raise error.CommandFailedError(proc.args, proc.returncode, stderr_data) return proc.returncode, ''.join(output_chunks)
def wait_execute(proc, exit_on_error, capture_output=True, print_output=True, timeout=None, ninja_command=False): """Looks after a command as it runs, and prints/returns its output after.""" def _print(s): if print_output: logger.debug(s) _print('---------------------------------------') output_chunks = [] current_line = [] wait_timeout(proc, timeout) for chunk in iter(lambda: proc.stdout.read(100), b''): if print_output: local_logging.send_output(chunk) if ninja_command and not DEBUG_PRINT: for x in chunk: if x == '\n': interpret_ninja_output(''.join(current_line)) current_line = [] else: current_line.append(x) elif not DEBUG_PRINT: sys.stdout.write('.') sys.stdout.flush() if capture_output: # According to: http://stackoverflow.com/questions/19926089, this is the # fastest way to build strings. output_chunks.append(chunk) proc.wait() if print_output: print() _print('---------------------------------------') if proc.returncode != 0: _print('| Return code is non-zero (%d).' % proc.returncode) if exit_on_error: _print('| Exit.') sys.exit(proc.returncode) return proc.returncode, ''.join(output_chunks)