RejectedSoftware Forums

Sign up

FileDescriptorEvent blocks I/O

Looks like FileDescriptorEvent blocks other vibe.d I/O

This code

/+ dub.json:
    {
        "name": "test",
        "dependencies": {
            "vibe-d:core": "0.7.29"
        }
    }
+/

import std.stdio;
import std.socket;
import std.datetime;
import vibe.core.core;

void main() {
    runTask({
        writeln("start task 1");
        yield();
        writeFile("dummy.txt", cast(immutable ubyte[]) "1234567890");
        writeln("end task 1");
        exitEventLoop();
    });
    runTask({
        writeln("start task 2");
        auto pair = socketPair();
        auto evt = createFileDescriptorEvent(pair[1].handle, FileDescriptorEvent.Trigger.any);
        //destroy(evt);
        writeln("end task 2");
    });
    runEventLoop();
}

prints

start task 1
start task 2
end task 2

end never exits the event loop.

Looks like Task 1 hangs on writeFile().

If to uncomment destroy(evt) then code works as expected.

Re: FileDescriptorEvent blocks I/O

Shorter test case (Issue 1583)

/+ dub.json:
    {
        "name": "test",
        "dependencies": {
            "vibe-d:core": "0.7.29"
        }
    }
+/

import std.stdio;
import std.socket;
import std.datetime;
import vibe.core.core;

void main() {
    runTask({
        writeln("start task");
        auto pair = socketPair();
        auto evt = createFileDescriptorEvent(pair[1].handle, FileDescriptorEvent.Trigger.any);
        //destroy(evt);
        writeFile("dummy.txt", cast(immutable ubyte[]) "1234567890");
        writeln("end task");
        exitEventLoop();
    });
    runEventLoop();
}

Re: FileDescriptorEvent blocks I/O

Am 03.10.2016 um 23:59 schrieb Jack Applegame:

Shorter test case (Issue 1583)

/+ dub.json:
    {
        "name": "test",
        "dependencies": {
            "vibe-d:core": "0.7.29"
        }
    }
+/

import std.stdio;
import std.socket;
import std.datetime;
import vibe.core.core;

void main() {
    runTask({
        writeln("start task");
        auto pair = socketPair();
        auto evt = createFileDescriptorEvent(pair[1].handle, FileDescriptorEvent.Trigger.any);
        //destroy(evt);
        writeFile("dummy.txt", cast(immutable ubyte[]) "1234567890");
        writeln("end task");
        exitEventLoop();
    });
    runEventLoop();
}

I'll have to look into where exactly it hangs - it could be stuck in
libevent - but one issue is that socketPair creates the sockets in
blocking mode. You'd either have to use the Posix socketpair function
together with SOCK_NONBLOCK, or use fnctl on the socket(s) created
by socketPair to set them to non-blocking mode after creation.

Re: FileDescriptorEvent blocks I/O

On Tue, 4 Oct 2016 16:24:30 +0200, Sönke Ludwig wrote:

I'll have to look into where exactly it hangs - it could be stuck in
libevent - but one issue is that socketPair creates the sockets in
blocking mode. You'd either have to use the Posix socketpair function
together with SOCK_NONBLOCK, or use fnctl on the socket(s) created
by socketPair to set them to non-blocking mode after creation.

Does FileDescriptorEvent work properly with non-blocking sockets only?

Another question:
after waiting for both read and write event, how to determine which event type occurred?

evt.wait(FileDescriptorEvent.Trigger.any);
if(???) {
    // writting
} else {
    // reading
}

Re: FileDescriptorEvent blocks I/O

On Tue, 04 Oct 2016 14:54:06 GMT, Jack Applegame wrote:
Does FileDescriptorEvent work properly with non-blocking sockets only?

Another question:
after waiting for both read and write event, how to determine which event type occurred?

evt.wait(FileDescriptorEvent.Trigger.any);
if(???) {
    // writting
} else {
    // reading
}

I found m_activeEvents member in Libevent2FileDescriptorEvent. It is exactly what I need.
Can I create a pull request to make this field public accessible?
At this time createFiledescriptorEvent implemented only for libevent driver, so this should not be a breaking change.

Re: FileDescriptorEvent blocks I/O

On Tue, 04 Oct 2016 15:24:52 GMT, Jack Applegame wrote:

I found m_activeEvents member in Libevent2FileDescriptorEvent. It is exactly what I need.
Can I create a pull request to make this field public accessible?
At this time createFiledescriptorEvent implemented only for libevent driver, so this should not be a breaking change.

It's bad idea, because m_activeEvents in theory could change at any time.

wait can return wrapper instead bool:

struct Result {
    bool m_flag;
    Trigger events;
    alias m_flag this;
}

Sönke, what do you think about this?