Redirecting stderr for each subprocess


I don’t figure how to redirect stderr for a subprocess… I’ve browsed the std.ChildProcess sources and various posts on this matter on Internet (there are not many), but without luck… I’m using 0.12.0-dev.1773+8a8fd47d2.

To learn zig subprocesses, i’m writing a toy program to compile a list of C files. I’ve already wrote such a program in Python, C (with fork/dup2/exec), Go (with exec.Command) and Rust (with process::Command).

In Zig, i’m stuck with stderr redirection and i don’t understand where is my mistake.
Given a list of C source namefiles, i’m using a for loop to

  1. create a error file for each c source file
const fd_err = try fs.cwd().createFile(name_err_file, .{});
defer fd_err.close()
  1. create a subprocess to run c99 -c name_src_file
var proc = std.ChildProcess.init(&[_][]const u8{ "c99", "-c", fic }, allocator);
proc.stderr_behavior = .Ignore;
proc.stderr = fd_err;
try proc.spawn();
  1. Then another for loop allows me to wait all these subprocesses, check the return statuses and, if all went fine, run another subprocess to link and produce the final executable.

The whole program does its job, but it seems the subprocesses don’t take my stderr into account… The error files are created and the error messages are not displayed, but the error files stay empty… (i expect some lines if there’s errors in my C files…these lines are displayed if i remove the proc_stderr_behavior and proc.stderr lines)

I suspect i misunderstand the input/output redirections of zig subprocesses. So, any help or pointer would be appreciated.

have you tried using?:

proc.stderr_behavior = .Pipe;

I think with .Ignore the value of .stderr becomes overwritten with a null handle / output gets thrown away. I haven’t really used this, just looks like that to me from reading the docs and having a quick look at source code.

Also look at these code pieces they also seem to be using pipe, when they are interested in the output:


Thanks for your suggestions…

Yes, i have tried .Pipe for stderr_behavior (in fact, i’ve tested all the options as i was unsure of their respective effects :slight_smile: ). No dice…
But i’m gonna investigate further the .Pipe option in regards of the links you gave…

Thanks to Sze’s suggestions, I finally have a code that seems to behave as expected.

Having said that, I have to admit that this code seems rather odd to me: i just wanted an equivalent of the good old c99 -c foo.c 2> err
I don’t really understand what child.stderr stands for… It’s a ?File, so I thought I could make it point to a file of my choice, like 2> does in shell. But that doesn’t seem to be the case…
I guess, even if this code works better than the previous one, I’m probably missing something because it seems quite laborious…

Anyway… here’s my modified point 2:

var proc = std.ChildProcess.init(&[_][]const u8{ "c99", "-c", fic }, allocator);
proc.stderr_behavior = .Pipe;
// proc.stderr = fd_err; // what is it for?
try proc.spawn();
const myStderr = try proc.stderr.?.reader().readAllAlloc(allocator, std.math.maxInt(usize)); // sounds violent to me
try fd_err.writer.print("{s}", .{myStderr})
1 Like