run method
Run a process and wait for it to complete.
Implementation
Future<ProcessOutput> run(ProcessConfig config) async {
final sw = Stopwatch()..start();
final process = await Process.start(
config.command,
config.args,
workingDirectory: config.workDir,
environment: config.env,
runInShell: config.runInShell,
);
final pid = process.pid;
_processes[pid] = process;
_processInfo[pid] = ProcessInfo(
pid: pid,
command: config.fullCommand,
startTime: DateTime.now(),
);
_eventController.add(ProcessStarted(pid, config.fullCommand));
// Send stdin if provided
if (config.stdin != null) {
process.stdin.write(config.stdin);
await process.stdin.close();
}
final stdoutBuf = StringBuffer();
final stderrBuf = StringBuffer();
final stdoutSub = process.stdout
.transform(const SystemEncoding().decoder)
.listen((data) {
if (config.captureStdout) stdoutBuf.write(data);
_eventController.add(StdoutData(pid, data));
});
final stderrSub = process.stderr
.transform(const SystemEncoding().decoder)
.listen((data) {
if (config.captureStderr) stderrBuf.write(data);
_eventController.add(StderrData(pid, data));
});
int exitCode;
var killed = false;
if (config.timeout != null) {
exitCode = await process.exitCode.timeout(
config.timeout!,
onTimeout: () {
process.kill(ProcessSignal.sigterm);
killed = true;
return -1;
},
);
} else {
exitCode = await process.exitCode;
}
await stdoutSub.cancel();
await stderrSub.cancel();
sw.stop();
_processInfo[pid]?.status = killed
? ProcessStatus.killed
: ProcessStatus.exited;
_processes.remove(pid);
_eventController.add(ProcessExited(pid, exitCode));
return ProcessOutput(
exitCode: exitCode,
stdout: stdoutBuf.toString(),
stderr: stderrBuf.toString(),
duration: sw.elapsed,
pid: pid,
killed: killed,
);
}