vibe-d / eventcore

High performance proactor event loop abstraction library
MIT License
60 stars 42 forks source link

Trying to get StreamSocketSlot but have none. #73

Open TETYYS opened 6 years ago

TETYYS commented 6 years ago

On unknown circumstances, when trying to close a TCPConnection an assert occurs:

core.exception.AssertError@../../.dub/packages/taggedalgebraic-0.10.11/taggedalgebraic/source/taggedalgebraic.d(781): Trying to get StreamSocketSlot but have none.
??:? _d_assert_msg [0xf6ee7bae]
??:? pure nothrow ref @safe inout(eventcore.drivers.posix.sockets.StreamSocketSlot) taggedalgebraic.get!(eventcore.drivers.posix.sockets.StreamSocketSlot, eventcore.internal.utils.AlgebraicChoppedVector!(eventcore.drivers.posix.driver.FDSlot, eventcore.drivers.posix.sockets.StreamSocketSlot, eventcore.drivers.posix.sockets.StreamListenSocketSlot, eventcore.drivers.posix.sockets.DgramSocketSlot, eventcore.drivers.posix.dns.DNSSlot, eventcore.drivers.posix.watchers.WatcherSlot, eventcore.drivers.posix.events.EventSlot, eventcore.drivers.posix.signals.SignalSlot).AlgebraicChoppedVector.U).get(ref inout(taggedalgebraic.TaggedAlgebraic!(eventcore.internal.utils.AlgebraicChoppedVector!(eventcore.drivers.posix.driver.FDSlot, eventcore.drivers.posix.sockets.StreamSocketSlot, eventcore.drivers.posix.sockets.StreamListenSocketSlot, eventcore.drivers.posix.sockets.DgramSocketSlot, eventcore.drivers.posix.dns.DNSSlot, eventcore.drivers.posix.watchers.WatcherSlot, eventcore.drivers.posix.events.EventSlot, eventcore.drivers.posix.signals.SignalSlot).AlgebraicChoppedVector.U).TaggedAlgebraic)) [0x55c88dae]
??:? pure nothrow ref @property @safe eventcore.drivers.posix.sockets.StreamSocketSlot eventcore.internal.utils.AlgebraicChoppedVector!(eventcore.drivers.posix.driver.FDSlot, eventcore.drivers.posix.sockets.StreamSocketSlot, eventcore.drivers.posix.sockets.StreamListenSocketSlot, eventcore.drivers.posix.sockets.DgramSocketSlot, eventcore.drivers.posix.dns.DNSSlot, eventcore.drivers.posix.watchers.WatcherSlot, eventcore.drivers.posix.events.EventSlot, eventcore.drivers.posix.signals.SignalSlot).AlgebraicChoppedVector.FullField.streamSocket() [0x55c85eef]
??:? _D9eventcore7drivers5posix7sockets__T23PosixEventDriverSocketsHTCQClQCeQBz5epoll14EpollEventLoopZQCi8shutdownMFNbNfSQEk6driver__T6HandleVAyaa12_73747265616d536f636b6574TSQGmQCc__TQByVQBua6_736f636b6574TSQHtQDj__TQDfVQDba2_6664TmVmN1ZQEaVQBjS1N1ZQEmVQDcS1S1N1ZQFabbZv [0x55c7d575]
??:? nothrow @safe void vibe.core.net.TCPConnection.close() [0x55c41dcd]
??:? void myprogram.method(shared(MyObject), bool).__lambda3() [0x55b17373]
??:? nothrow @trusted void vibe.core.core.setTimer(core.time.Duration, void delegate(), bool).__lambda4() [0x55c39d3c]
??:? @safe void vibe.core.core.createTimer(void delegate() nothrow @safe).__lambda2(void delegate() nothrow @safe, vibe.core.core.Timer) [0x55c39f75]
??:? void vibe.core.task.TaskFuncInfo.set!(void function(void delegate() nothrow @safe, vibe.core.core.Timer) @safe*, void delegate() nothrow @safe, vibe.core.core.Timer).set(ref void function(void delegate() nothrow @safe, vibe.core.core.Timer) @safe*, ref void delegate() nothrow @safe, ref vibe.core.core.Timer).callDelegate(ref vibe.core.task.TaskFuncInfo) [0x55c568f1]
??:? void vibe.core.task.TaskFuncInfo.call() [0x55c55299]
??:? nothrow void vibe.core.task.TaskFiber.run() [0x55c548a1]
??:? void core.thread.Fiber.run() [0xf6eec65b]
??:? fiber_entryPoint [0xf6eeba26]
??:? [0xffffffff]

TCPConnection is not closed from anywhere else in the code.

TETYYS commented 6 years ago

Library versions:

"botan": "1.12.9",
"botan-math": "1.0.3",
"diet-ng": "1.4.5",
"eventcore": "0.8.35",
"libasync": "0.8.3",
"libevent": "2.0.2+2.0.16",
"memutils": "0.4.10",
"mir-linux-kernel": "1.0.0",
"openssl": "1.1.6+1.0.1g",
"stdx-allocator": "2.77.2",
"taggedalgebraic": "0.10.11",
"vibe-core": "1.4.0",
"vibe-d": "0.8.4"

~I think this issue happens because each worker thread have their own event loops and each event loop has their own FD pool. When connect and close are combined with runWorkerTaskH, sometimes close is called on different event loop the connection was created on.~

This code snippet reproduces this issue (runTask instead of runWorkerTaskH gives same result):

import vibe.vibe;

void fx()
{
    TCPConnection conn;
    setTimer(2.seconds, {
        conn.close();
    });
    conn = connectTCP("google.com", 80);
}

void main()
{
    foreach (x; 0 .. 100) {
        runWorkerTaskH(&fx);
    }

    runApplication();
}

When this runs fine:

import vibe.vibe;

void fx()
{
    TCPConnection conn;
    runTask((TCPConnection c), {
        sleep(2.seconds);
        c.close();
    }, conn);
    conn = connectTCP("google.com", 80);
}

void main()
{
    foreach (x; 0 .. 100) {
        runWorkerTaskH(&fx);
    }

    runApplication();
}

Now this points that this is reference count issue.