Cloudef / zig-aio

io_uring like asynchronous API and coroutine powered IO tasks for zig
https://cloudef.github.io/zig-aio/
MIT License
175 stars 6 forks source link

Example coro_wttr with aio_options (debug=true) panics with exit code 0xC0000005 on windows. #10

Closed MaratBR closed 2 months ago

MaratBR commented 2 months ago

As the title says. I was using this example as a starting point when I encountered this issue.

I can provide exact code later but basically, the app crashes when spawnForCompletition is called with exit code 0xC0000005. On windows that indicates memory access violation (read NULL pointer or from unallocated/freed space). It happens if I have this in my main.zig:

pub const aio_options: aio.Options = .{
    .debug = false, // set to true to enable debug logs
};

Windows 11, x86_64. I am using zig-aio from this commit: 630207a1c4dede36ee842e4f51ca914b49d1c0b0 (latest commit as of writing this).

MaratBR commented 2 months ago

Can confirm that it also happens on WSL2. Was tested on zig 0.13 and 0.14.0-dev.1304+7d54c62c8

Minimal example:

const std = @import("std");
const aio = @import("aio");
const coro = @import("coro");

pub const aio_options: aio.Options = .{
    .debug = true, // changing this to false fixes the issue
};

fn printEverySecond(msg: []const u8) !void {
    while (true) {
        try coro.io.single(aio.Timeout{ .ns = std.time.ns_per_s });
        std.log.info("{s}", .{msg});
    }
}

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

    var scheduler = try coro.Scheduler.init(allocator, .{});
    defer scheduler.deinit();

    var tpool: coro.ThreadPool = try coro.ThreadPool.init(gpa.allocator(), .{});
    defer tpool.deinit();

    _ = try scheduler.spawn(printEverySecond, .{"scheduler"}, .{});
    _ = try tpool.spawnForCompletition(&scheduler, printEverySecond, .{"thread pool"}, .{});

    try scheduler.run(.wait);
}
Cloudef commented 2 months ago

Thanks, I was able to reproduce this. It only happens on posix and windows backend, so most likely issue within the io_uring emulation component.

Cloudef commented 2 months ago

Both windows and posix were hitting stack canaries. They require larger stack when debug prints are enabled. The stack sizes for the spawnForCompletition's wrapper task and TimerQueue are reduced to the minimum because they won't run actual user code. On the other hand the default stack size for scheduler.spawn is pretty generous 1MB, while any threads made by spawnForCompletition for example, use whatever the default is in zig's std.

Should be fixed by: https://github.com/Cloudef/zig-aio/commit/ee6932f9e556405808daecba2175f79b3a831e12 https://github.com/Cloudef/zig-aio/commit/a6ba5fa8dffc45ec3ab37bc29235022b90841264