Skip to content

Commit

Permalink
Avoid double-resumption of task on active connection close. Fixes #1376.
Browse files Browse the repository at this point in the history
With a concurrent read operation, the libevent active TCP connection close function could result in a double-resumption of the read task, if the close happened in the same event loop round as a read-ready or close event on the socket.
  • Loading branch information
s-ludwig committed Jan 27, 2016
1 parent e933ceb commit bfdf1a8
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
7 changes: 4 additions & 3 deletions source/vibe/core/drivers/libevent2_tcp.d
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ package nothrow extern(C)

auto f = ctx.readOwner;
try {
if (f && f.running)
if (f && f.running && ctx.state != ConnectionState.activeClose)
ctx.core.resumeTask(f);
} catch (UncaughtException e) {
logWarn("Got exception when resuming task onSocketRead: %s", e.msg);
Expand Down Expand Up @@ -698,7 +698,8 @@ package nothrow extern(C)
string errorMessage;
if (status & BEV_EVENT_EOF) {
logDebug("Connection was closed (fd %d).", ctx.socketfd);
ctx.state = ConnectionState.passiveClose;
if (ctx.state != ConnectionState.activeClose)
ctx.state = ConnectionState.passiveClose;
evbuffer* buf = bufferevent_get_input(buf_event);
if (evbuffer_get_length(buf) == 0) free_event = true;
} else if (status & BEV_EVENT_TIMEOUT) {
Expand All @@ -719,7 +720,7 @@ package nothrow extern(C)

ctx.core.eventException = ex;

if (ctx.readOwner && ctx.readOwner.running) {
if (ctx.readOwner && ctx.readOwner.running && ctx.state != ConnectionState.activeClose) {
logTrace("resuming corresponding task%s...", ex is null ? "" : " with exception");
if (ctx.readOwner.fiber.state == Fiber.State.EXEC) ctx.exception = ex;
else ctx.core.resumeTask(ctx.readOwner, ex);
Expand Down
4 changes: 4 additions & 0 deletions tests/vibe.core.net.1376/dub.sdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name "tests"
description "TCP disconnect task issue"
dependency "vibe-d:core" path="../../"
versions "VibeDefaultMain"
29 changes: 29 additions & 0 deletions tests/vibe.core.net.1376/source/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import vibe.core.core;
import vibe.core.net;
import core.time : msecs;

shared static this()
{
listenTCP(11375,(conn){
auto td = runTask({
ubyte [3] buf;
try {
conn.read(buf);
assert(false, "Expected read() to throw an exception.");
} catch (Exception) {} // expected
});
conn.close();
});

runTask({
auto conn = connectTCP("127.0.0.1", 11375);
conn.write("a");
conn.close();

conn = connectTCP("127.0.0.1", 11375);
conn.close();

sleep(50.msecs);
exitEventLoop();
});
}

0 comments on commit bfdf1a8

Please sign in to comment.