Skip to content

Commit 3b650c5

Browse files
omerfirmakAndrejMitrovic
authored andcommitted
Fix self conn deadlock
When a node goes to sleep and manages to send a request to itself the request gets queued. Once it wakes up from the sleep it will try to process that request synchronous to own event loop and locks itself. Queued messages should be handled async to the event loop.
1 parent 8f533dd commit 3b650c5

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

source/geod24/LocalRest.d

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,14 @@ public final class RemoteAPI (API, alias S = VibeJSONSerializer!()) : API
770770

771771
auto sel_ret = C.select(read_list, write_list, 10.msecs);
772772

773-
if (!control.isSleeping())
773+
if (await_msgs.length > 0 && !control.isSleeping())
774774
{
775-
foreach (ref await_msg; await_msgs)
776-
handleCommand(await_msg.var.cmd, node, control.filter, await_msg.conn.resp_chn);
775+
scheduler.spawn({
776+
auto prev_await_msgs = await_msgs;
777+
foreach (ref await_msg; prev_await_msgs)
778+
handleCommand(await_msg.var.cmd, node, control.filter, await_msg.conn.resp_chn);
779+
});
777780
await_msgs.length = 0;
778-
assumeSafeAppend(await_msgs);
779781
}
780782

781783
if (!sel_ret.success)
@@ -2544,3 +2546,47 @@ unittest
25442546
assert(test.pubkey() == 42);
25452547
assert(called);
25462548
}
2549+
2550+
// Self connection deadlock scenario
2551+
// without the proper fix, this test should hang
2552+
unittest
2553+
{
2554+
import core.atomic;
2555+
2556+
static interface API
2557+
{
2558+
@safe:
2559+
public void call0 ();
2560+
public int get44 ();
2561+
}
2562+
2563+
__gshared Listener!API node1Addr;
2564+
2565+
static class Node : API
2566+
{
2567+
private RemoteAPI!API self;
2568+
2569+
@trusted:
2570+
public override void call0 ()
2571+
{
2572+
this.self = new RemoteAPI!API(atomicLoad(node1Addr));
2573+
this.self.ctrl.sleep(1.seconds);
2574+
assert(this.self.get44() == 44);
2575+
}
2576+
2577+
public override int get44 ()
2578+
{
2579+
return 44;
2580+
}
2581+
}
2582+
2583+
auto node1 = RemoteAPI!API.spawn!Node();
2584+
scope (exit)
2585+
{
2586+
node1.ctrl.shutdown();
2587+
thread_joinAll();
2588+
}
2589+
2590+
atomicStore(node1Addr, node1.ctrl.listener());
2591+
node1.call0();
2592+
}

0 commit comments

Comments
 (0)