Hey there! First time posting to ziggit, hoping a relatively easy question here.
I’m attempting to spawn a local “server” as a child process that supports communication over stdin / stdout. I’ve tried a few different ways of doing this, but I keep running into some odd errors, and I’m not sure how to proceed.
Here’s a minimal example case, just using tail as the “server”.
const std = @import("std");
const Io = std.Io;
pub fn main(init: std.process.Init) !void {
const alloc = init.arena.allocator();
const io = init.io;
var tail: std.process.Child = try std.process.spawn(io, .{
.argv = &.{"tail"},
.stdin = .pipe,
.stdout = .pipe,
});
const buf_w = try alloc.alloc(u8, 1024);
const buf_r = try alloc.alloc(u8, 1024);
var w: Io.Writer = tail.stdin.?.writer(io, buf_w).interface;
var r: Io.Reader = tail.stdout.?.reader(io, buf_r).interface;
_ = try w.write("123456789\n");
try w.flush();
var out: [10]u8 = @splat(0);
try r.readSliceAll(&out);
std.debug.print("{s}\n", .{out});
}
In this case, I get a failure on the write side:
General protection exception (no address available)
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io.zig:453:29: 0x1039bb5 in operate (std.zig)
return io.vtable.operate(io.userdata, operation);
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File.zig:614:27: 0x11dace9 in writeStreaming (std.zig)
return (try io.operate(.{ .file_write_streaming = .{
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File/Writer.zig:126:36: 0x11da786 in drainStreaming (std.zig)
const n = w.file.writeStreaming(io, header, data, splat) catch |err| {
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File/Writer.zig:93:63: 0x11da19c in drain (std.zig)
.streaming, .streaming_simple => return drainStreaming(w, data, splat),
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/Writer.zig:319:39: 0x10365e2 in defaultFlush (std.zig)
while (w.end != 0) _ = try drainFn(w, &.{""}, 1);
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/Writer.zig:313:26: 0x11279e3 in flush (std.zig)
return w.vtable.flush(w);
^
/home/nickmonad/code/test-zig/src/test.zig:21:16: 0x11d25e5 in main (test.zig)
try w.flush();
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/start.zig:737:30: 0x11d32fe in callMain (std.zig)
return wrapMain(root.main(.{
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/start.zig:190:5: 0x11d20e1 in _start (std.zig)
asm volatile (switch (native_arch) {
^
fish: Job 1, 'zig run src/test.zig' terminated by signal SIGABRT (Abort)
If I change the write to use writeAll, that seems to progress, but then I get a similar error on the read side
_ = try w.writeAll("123456789\n");
var out: [10]u8 = @splat(0);
try r.readSliceAll(&out);
std.debug.print("{s}\n", .{out});
General protection exception (no address available)
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io.zig:453:29: 0x1039bb5 in operate (std.zig)
return io.vtable.operate(io.userdata, operation);
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File.zig:475:27: 0x10390f7 in readStreaming (std.zig)
return (try io.operate(.{ .file_read_streaming = .{
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File/Reader.zig:283:35: 0x1038bfb in readVecStreaming (std.zig)
const n = r.file.readStreaming(io, dest) catch |err| switch (err) {
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/File/Reader.zig:236:65: 0x10376a0 in readVec (std.zig)
.streaming, .streaming_simple => return readVecStreaming(r, data),
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/Reader.zig:429:37: 0x10eaefa in readVec (std.zig)
return n + (r.vtable.readVec(r, data[i..]) catch |err| switch (err) {
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/Reader.zig:688:21: 0x10ea4a7 in readSliceShort (std.zig)
i += readVec(r, &data) catch |err| switch (err) {
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/Io/Reader.zig:661:33: 0x10e9e17 in readSliceAll (std.zig)
const n = try readSliceShort(r, buffer);
^
/home/nickmonad/code/test-zig/src/test.zig:23:23: 0x11d2634 in main (test.zig)
try r.readSliceAll(&out);
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/start.zig:737:30: 0x11d326e in callMain (std.zig)
return wrapMain(root.main(.{
^
/nix/store/m8gzpx3c3w39wh36h5hvsy2m7vgig998-zig-0.16.0/lib/std/start.zig:190:5: 0x11d20e1 in _start (std.zig)
asm volatile (switch (native_arch) {
^
fish: Job 1, 'zig run src/test.zig' terminated by signal SIGABRT (Abort)
Any insight here would be greatly appreciated. Am I doing something weird with the stack allocated resources here, either the File handles or the Io interfaces, such that it’s pointing to invalid memory? Does the writing and reading need to be in separate threads? I know I’m not cleaning up resources fully, but I would assume I’d at least see the expected print result before there would be an issue there.
Thanks!