Skip to content

Passing Io.Duration to io.async as an arg when using FixedBufferAllocator causes thread to panic. #25900

@D-Berg

Description

@D-Berg

Zig Version

0.16.0-dev.1272+f3309a96a

Steps to Reproduce and Observed Behavior

Example program crashes when using FBA and works when using DBA with the following output. The panic is triggered when Io.Duration is passed as an argument but works fine otherwise.

zig run io_sleep.zig
f1 won
thread 188397274 panic: incorrect alignment
/Users/orion/.local/share/zigup/0.16.0-dev.1272+f3309a96a/files/lib/std/Io.zig:1534:46: 0x1026a54f7 in start (io_
sleep)
            const args_casted: *const Args = @ptrCast(@alignCast(context));
                                             ^
/Users/orion/.local/share/zigup/0.16.0-dev.1272+f3309a96a/files/lib/std/Io/Threaded.zig:405:16: 0x10260aac3 in st
art (io_sleep)
        ac.func(ac.contextPointer(), ac.resultPointer());
               ^
/Users/orion/.local/share/zigup/0.16.0-dev.1272+f3309a96a/files/lib/std/Io/Threaded.zig:188:26: 0x10265ebb7 in wo
rker (io_sleep)
            closure.start(closure);
                         ^
/Users/orion/.local/share/zigup/0.16.0-dev.1272+f3309a96a/files/lib/std/Thread.zig:558:13: 0x1026463db in callFn_
_anon_15412 (io_sleep)
            @call(.auto, f, args);
            ^
/Users/orion/.local/share/zigup/0.16.0-dev.1272+f3309a96a/files/lib/std/Thread.zig:830:30: 0x10262a907 in entryFn
 (io_sleep)
                return callFn(f, args_ptr.*);
                             ^
???:?:?: 0x18591ec0b in __pthread_cond_wait (/usr/lib/system/libsystem_pthread.dylib)
???:?:?: 0x185919b7f in _pthread_cond_broadcast (/usr/lib/system/libsystem_pthread.dylib)
zsh: abort      zig run io_sleep.zig
const std = @import("std");
const Io = std.Io;

var global_buf: [4 * 1024 * 1024]u8 = undefined;
var fba_impl: std.heap.FixedBufferAllocator = .init(&global_buf);

var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
pub fn main() !void {
    const use_heap = false;
    const gpa = blk: {
        break :blk switch (use_heap) {
            true => debug_allocator.allocator(),
            false => fba_impl.threadSafeAllocator(),
        };
    };
    defer if (use_heap) {
        _ = debug_allocator.deinit();
    };

    var threaded_io: Io.Threaded = .init(gpa);
    defer threaded_io.deinit();

    const io = threaded_io.io();

    try worksWithFba(io);
    try breaksWithFba(io);
}

fn breaksWithFba(io: Io) !void {
    var f1 = io.async(Io.sleep, .{ io, Io.Duration.fromSeconds(1), .real });
    defer f1.cancel(io) catch {};

    var f2 = io.async(Io.sleep, .{ io, Io.Duration.fromSeconds(2), .real });
    defer f2.cancel(io) catch {};

    switch (try io.select(.{ .f1 = &f1, .f2 = &f2 })) {
        .f1 => std.debug.print("f1 won\n", .{}),
        .f2 => std.debug.print("f2 won\n", .{}),
    }
}

fn worksWithFba(io: Io) !void {
    var f1 = io.async(sleep, .{ io, 1, .real });
    defer f1.cancel(io) catch {};

    var f2 = io.async(sleep, .{ io, 2, .real });
    defer f2.cancel(io) catch {};

    switch (try io.select(.{ .f1 = &f1, .f2 = &f2 })) {
        .f1 => std.debug.print("f1 won\n", .{}),
        .f2 => std.debug.print("f2 won\n", .{}),
    }
}

fn sleep(io: Io, seconds: i64, clock: Io.Clock) !void {
    try io.sleep(.fromSeconds(seconds), clock);
}

Expected Behavior

I would assume it should work given any allocator.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions