Skip to content

Commit

Permalink
Fix: IOUring timer management
Browse files Browse the repository at this point in the history
The iouring module was wrongfully propagating to a non-timeout wait from
a timeout submitAndWait under certain circumstances, leading to timeouts
never happening.

`dirtyTimers` need to be toggled even when no timers were triggered.
This is because the timingwheel implementation doesn't return the exact
time the next timer is to be triggered, but maxes that at 255 * tick size.

Test Plan: `dub test`.
  • Loading branch information
skoppe committed Dec 29, 2024
1 parent 24dabe5 commit 1e69059
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 6 deletions.
10 changes: 5 additions & 5 deletions source/concurrency/io/iouring.d
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct IOUringContext {
// or even IORING_OP_LINK_TIMEOUT to link the timeout to the
// wakeup event
private bool dirtyTimers;
private long nextTimer;
private ulong nextTimer;
private shared bool needsWakeup;
private this(uint size) @trusted {
// TODO: look into `IORING_SETUP_SQPOLL` for fast submission
Expand Down Expand Up @@ -123,6 +123,7 @@ struct IOUringContext {

private int run(scope shared StopToken stopToken) @safe nothrow {
import core.atomic : atomicStore, MemoryOrder;
import core.stdc.errno;

assert(threadId == thisThreadID, "Thread that started IOUringContext must also drive it.");
pending.append(requests.popAll());
Expand All @@ -137,7 +138,7 @@ struct IOUringContext {
// will result in blocked request. Instead we need to cancel all requests
// until the stopToken is triggered.
// Would it be possible to cancel the whole context in one go?
if (rc < 0)
if (rc < 0 && !ETIMEDOUT)
return -rc;
atomicStore!(MemoryOrder.raw)(needsWakeup, false);

Expand Down Expand Up @@ -187,8 +188,7 @@ struct IOUringContext {
if (incr > 0) {
Timer* t;
wheels.advance(incr, t);
if (t !is null)
dirtyTimers = true;
dirtyTimers = true;
while (t !is null) {
auto next = t.next;
t.userdata(TimerTrigger.trigger);
Expand All @@ -201,7 +201,7 @@ struct IOUringContext {
import std.datetime.systime : Clock;
import core.time : hnsecs;

long now = Clock.currStdTime;
ulong now = Clock.currStdTime;
if (dirtyTimers) {
dirtyTimers = false;
auto nextTriggerOpt = wheels.timeUntilNextEvent(tickSize, now);
Expand Down
2 changes: 1 addition & 1 deletion source/during/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ struct Uring
if (_expect(r < 0, false)) return -errno;
return r;
}
return wait(want); // just simple wait
return wait(want, args); // just simple wait
}

/// ditto
Expand Down

0 comments on commit 1e69059

Please sign in to comment.