-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
async function called as synchronous #7793
Copy link
Copy link
Open
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behavior
Milestone
Description
Example:
const assert = @import("std").debug.assert;
var counter: u8 = 0;
var frame: anyframe = undefined;
fn asyncfunc() callconv(.Async) u8 {
suspend {
frame = @frame();
}
counter += 1;
return counter;
}
fn wrapasync() u8 {
return asyncfunc();
}
fn callit(inner: fn() u8) u8 {
return inner();
}
pub fn main() void {
assert(counter == 0);
var coro = async wrapasync();
assert(counter == 0);
resume frame;
assert(counter == 1);
const val1 = nosuspend await coro;
assert(counter == 1);
assert(val1 == 1);
_ = callit(wrapasync);
}
The first call to wrapasync() creates a coroutine. It suspends, is resumed, and finishes. Everything behaves as expected.
However, in the second call wrapasync is implicitly converted to fn() u8, and callit() calls it using the calling convention for regular function. The result is this:
thread NNNNN: panic: resumed an async function which already returned
..../async.zig:14:1: 0x234562 in wrapasync (async)
fn wrapasync() u8 {
^
...../async.zig:19:17: 0x23466e in callit (async)
return inner();
^
...../async.zig:32:24: 0x22d359 in main (async)
_ = callit(wrapasync);
^
/usr/lib/zig/std/start.zig:335:22: 0x204d8e in std.start.posixCallMainAndExit (async)
root.main();
^
/usr/lib/zig/std/start.zig:163:5: 0x204c62 in std.start._start (async)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
Aborted (core dumped)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behavior