Thread overview
non-block reading from pipe stdout
Oct 03, 2017
Oleg B
Oct 03, 2017
kdevel
Oct 03, 2017
Oleg B
Oct 03, 2017
kdevel
Oct 03, 2017
Oleg B
Oct 03, 2017
kdevel
Oct 03, 2017
Oleg B
October 03, 2017
Hello. I run program through std.process.pipeShell and want to read from it stdout in loop. How do this non-blocking?

I try

	int fd = p.stdout.fileno;
	int flags = fcntl(fd, F_GETFL, 0);
	flags |= O_NONBLOCK;
	fcntl(fd, F_SETFL, flags);

but get error "Resource temporarily unavailable".
October 03, 2017
On Tuesday, 3 October 2017 at 00:22:28 UTC, Oleg B wrote:
> but get error "Resource temporarily unavailable".

You get EAGAIN because there is no data available at the time of reading.

From the manpage of read:

ERRORS
       EAGAIN Non-blocking  I/O has been selected using O_NONBLOCK and no data
              was immediately available for reading.

October 03, 2017
On Tuesday, 3 October 2017 at 10:45:21 UTC, kdevel wrote:
> On Tuesday, 3 October 2017 at 00:22:28 UTC, Oleg B wrote:
>> but get error "Resource temporarily unavailable".
>
> You get EAGAIN because there is no data available at the time of reading.
>
> From the manpage of read:
>
> ERRORS
>        EAGAIN Non-blocking  I/O has been selected using O_NONBLOCK and no data
>               was immediately available for reading.

And I can't check this without using exception handling?
October 03, 2017
On Tuesday, 3 October 2017 at 10:45:21 UTC, kdevel wrote:
> On Tuesday, 3 October 2017 at 00:22:28 UTC, Oleg B wrote:
>> but get error "Resource temporarily unavailable".
>
> You get EAGAIN because there is no data available at the time of reading.
>
> From the manpage of read:
>
> ERRORS
>        EAGAIN Non-blocking  I/O has been selected using O_NONBLOCK and no data
>               was immediately available for reading.

I found only one way: C-style

        auto pp = pipeShell(updaterScriptCommand, Redirect.all,
                            null, Config.none, workDir);

        import core.sys.posix.unistd : read;
        import core.stdc.errno;
        import core.sys.posix.fcntl;

        int fd = pp.stdout.fileno;
        int flags = fcntl(fd, F_GETFL, 0);
        flags |= O_NONBLOCK;
        fcntl(fd, F_SETFL, flags); // C-style setting file config

        char[256] buf;
        while (!tryWait(pp.pid).terminated)
        {
            auto cnt = read(fd, buf.ptr, buf.length); // C-style reading
            if (cnt == -1 && errno == EAGAIN) // C-style error checking
                yield();
            else if (cnt > 0)
            {
                doSomething(buf[0..cnt]);
                yield();
            }
        }
October 03, 2017
On Tuesday, 3 October 2017 at 11:36:28 UTC, Oleg B wrote:
>>        EAGAIN Non-blocking  I/O has been selected using O_NONBLOCK and no data
>>               was immediately available for reading.
>
> And I can't check this without using exception handling?

Your programm shall not read before data is available. Use core.sys.posix.sys.select to check if read would block on a blocking socket.

October 03, 2017
On Tuesday, 3 October 2017 at 12:20:09 UTC, Oleg B wrote:
>         while (!tryWait(pp.pid).terminated)
>         {
>             auto cnt = read(fd, buf.ptr, buf.length); // C-style reading
>             if (cnt == -1 && errno == EAGAIN) // C-style error checking
>                 yield();
>             else if (cnt > 0)
>             {
>                 doSomething(buf[0..cnt]);
>                 yield();
>             }
>         }

IMHO a program should sleep (consume 0 CPU time and 0 energy) if there is nothing to process. This is best accomplished by not polling on a file descriptor in order to check if data has arrived. If your program must yield() there's probably something wrong with the design. I would suggest you put all the filedescriptors into a fd_set an then select(3) on the set.
October 03, 2017
On Tuesday, 3 October 2017 at 12:32:43 UTC, kdevel wrote:
> IMHO a program should sleep (consume 0 CPU time and 0 energy) if there is nothing to process. This is best accomplished by not polling on a file descriptor in order to check if data has arrived. If your program must yield() there's probably something wrong with the design. I would suggest you put all the filedescriptors into a fd_set an then select(3) on the set.

Programs based on fibers can't sleep while wait data and it's not a design problem.