zig icon indicating copy to clipboard operation
zig copied to clipboard

ChildProcess: Basic Block in function 'std.child_process.ChildProcess.spawnPosix' does not have terminator!

Open catdevnull opened this issue 3 years ago • 2 comments

Zig Version

0.10.0-dev.2836+2360f8c49

Steps to Reproduce

pub const io_mode = .evented;
const std = @import("std");

pub fn fetch_item(allocator: std.mem.Allocator, cmd: []const u8, item: []const u8) void {
    const result = std.ChildProcess.exec(.{
        .allocator = allocator,
        .argv = &.{ cmd, item },
    }) catch |err| {
        std.log.err("Error: {any}", .{err});
        return;
    };
    std.log.debug("stdout: {s}", .{result.stdout});
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();

    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);
    if (args.len <= 1) {
        return error.MissingCommand;
    }
    const cmd = args[1];
    std.log.debug("Running command `{s}`", .{cmd});

    var batch = std.event.Batch(void, 2, .auto_async).init();

    var item_list = std.ArrayList([]const u8).init(allocator);
    defer item_list.deinit();
    defer for (item_list.items) |item| allocator.free(item);

    const reader = std.io.getStdIn().reader();
    while (reader.readUntilDelimiterAlloc(allocator, '\n', 9999999) catch |err| switch (err) {
        error.EndOfStream => null,
        else => return err,
    }) |result| {
        try item_list.append(result);
    }

    const Context = struct { frame: @Frame(fetch_item) };

    var context_list = std.ArrayList(*Context).init(allocator);
    defer context_list.deinit();
    defer for (context_list.items) |ctx| allocator.destroy(ctx);

    for (item_list.items) |item| {
        var ctx = try allocator.create(Context);
        errdefer allocator.destroy(ctx);
        try context_list.append(ctx);
        ctx.frame = async fetch_item(allocator, cmd, item);
        batch.add(&ctx.frame);
    }

    batch.wait();
}

Expected Behavior

The compiler builds the file.

Actual Behavior

Code Generation [970/1010] std.mem.Allocator.allocAdvancedWithRetAddr... broken LLVM module found: Basic Block in function 'std.child_process.ChildProcess.spawnPosix' does not have terminator!
label %OkResume
Instruction does not dominate all uses!
  %28 = load { %std.child_process.ChildProcess.Term, i16 }*, { %std.child_process.ChildProcess.Term, i16 }** %6, align 8, !dbg !30794
  %41 = bitcast { %std.child_process.ChildProcess.Term, i16 }* %28 to i8*, !dbg !30794

This is a bug in the Zig compiler.thread 25498 panic: 
Unable to dump stack trace: debug info stripped

catdevnull avatar Jul 03 '22 17:07 catdevnull

In case this helps, I ran into this with a smaller repro:

const std = @import("std");
pub const io_mode = .evented;

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    var allocator = gpa.allocator();
    defer _ = gpa.deinit();

    _ = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = &[_][]const u8{ "echo", "hello" } });
}

Changing the io_mode to .blocking compiles correctly.

sdnts avatar Aug 14 '22 16:08 sdnts

Having the same issue with latest 0.11.0-dev.10+1780d7a34, the bug prevents running child processes in an evented program at all.

theseyan avatar Nov 02 '22 03:11 theseyan