Zig 中的 child process 簡介
在工作中,難免會去重複執行某些某個任務,直到其成功爲止。比如下載依賴,之前我的做法是用 Shell
while ! do something; do echo retry; done
這樣雖然可以,但是有些麻煩,於是就想能不能實現個 cli,來替我們執行,如果用 C 實現的話,可以預想到的,就是 fork + exec,貌似也不是很麻煩。
但是如果要在主進程中,等待 child 完成的之前,收集 child 的 stdout,而不堵塞主進程,那就要採用異步的 API 來輪訓 stdout,比如 select 或 poll, Zig 裏面有個 child_process.zig[1],它裏面把 fork + exec + poll 都封裝好了,直接使用即可,一些關鍵函數:
/// Collect the output from the process's stdout and stderr. Will return once all output
/// has been collected. This does not mean that the process has ended. `wait` should still
/// be called to wait for and clean up the process.
///
/// The process must be started with stdout_behavior and stderr_behavior == .Pipe
pub fn collectOutput(
child: ChildProcess,
stdout: *std.ArrayList(u8),
stderr: *std.ArrayList(u8),
max_output_bytes: usize,
) !void {
debug.assert(child.stdout_behavior == .Pipe);
debug.assert(child.stderr_behavior == .Pipe);
// we could make this work with multiple allocators but YAGNI
if (stdout.allocator.ptr != stderr.allocator.ptr or
stdout.allocator.vtable != stderr.allocator.vtable)
@panic("ChildProcess.collectOutput only supports 1 allocator");
var poller = std.io.poll(stdout.allocator, enum { stdout, stderr }, .{
.stdout = child.stdout.?,
.stderr = child.stderr.?,
});
defer poller.deinit();
while (try poller.poll()) {
if (poller.fifo(.stdout).count > max_output_bytes)
return error.StdoutStreamTooLong;
if (poller.fifo(.stderr).count > max_output_bytes)
return error.StderrStreamTooLong;
}
stdout.* = fifoToOwnedArrayList(poller.fifo(.stdout));
stderr.* = fifoToOwnedArrayList(poller.fifo(.stderr));
}
這是收集 stdout 的,創建進程的地方在 spawnPosix
中,感興趣的可以自行查看,後來有機會再來介紹。
推薦閱讀
-
microHOWTO: Capture the output of a child process in C[2]
-
Forking is Cool, or: A Unix Shell in Zig, or: Dave Learns How to Fork[3]
參考資料
[1] child_process.zig: https://github.com/ziglang/zig/blob/7dd1cf26f9b0cb104ada166a10ff356ca272577a/lib/std/child_process.zig#L1
[2] microHOWTO: Capture the output of a child process in C: http://www.microhowto.info/howto/capture_the_output_of_a_child_process_in_c.html
[3] Forking is Cool, or: A Unix Shell in Zig, or: Dave Learns How to Fork: https://ratfactor.com/zig/forking-is-cool
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/uAwpDnYCp5ts7mB8aJpaAQ