Thread overview
Is there any way for non-blocking IO with phobos?
Nov 13, 2018
Sobaya
Nov 13, 2018
Rémy Mouëza
Nov 14, 2018
Kagamin
November 13, 2018
I want to connect to a server and communicate with ssh.

So I tried to spawn the process of ssh using pipeProcess function, and read/write with its pipe's stdin and stdout.

But I don't know how many lines are sent from the server for an input, so readln function blocks.

I think this can be solved with non-blocking IO, but I cannot find how do I use non-blocking IO with phobos.

Please give me any ideas.

Thanks.
November 13, 2018
On 11/13/18 8:52 AM, Sobaya wrote:
> I want to connect to a server and communicate with ssh.
> 
> So I tried to spawn the process of ssh using pipeProcess function, and read/write with its pipe's stdin and stdout.
> 
> But I don't know how many lines are sent from the server for an input, so readln function blocks.
> 
> I think this can be solved with non-blocking IO, but I cannot find how do I use non-blocking IO with phobos.
> 
> Please give me any ideas.

Phobos process pipes use std.stdio.File and therefore FILE * as underlying mechanism. I don't think you can do this non-blocking.

You could extract the FILE *, and extract the file descriptor, and do it manually. Only way I can think of.

-Steve

November 13, 2018
On Tuesday, 13 November 2018 at 13:52:57 UTC, Sobaya wrote:
> I want to connect to a server and communicate with ssh.
>
> So I tried to spawn the process of ssh using pipeProcess function, and read/write with its pipe's stdin and stdout.
>
> But I don't know how many lines are sent from the server for an input, so readln function blocks.
>
> I think this can be solved with non-blocking IO, but I cannot find how do I use non-blocking IO with phobos.
>
> Please give me any ideas.
>
> Thanks.

I had some success with the "hasdata" package available on code.dlang.org:
https://code.dlang.org/packages/hasdata

Below is a sample program that I have tested on Linux:
--------------------------------------------------
/+ dub.sdl:
name "non-blocking-io"
description "A non blocking IO example using hasdata."
authors "Rémy J. A. Mouëza"
license "MIT"
dependency "hasdata" version="~>1.1.0"
-- sourcePaths "."
configuration "application" {
	targetType "executable"
}
+/
// Written in the D programming language: http://dlang.org
import std.process;
import std.string;
import std.range;
import std.stdio;

import core.thread;

import hasdata;


struct NonBlockingPs {
    /// The underlying vlc process.
    ProcessPipes ps;
    alias ps this;

    immutable bufsize = 8;

    this (string [] args...) {
        this.ps = pipeProcess (args,
                                Redirect.stdin  |
                                Redirect.stdout |
                                Redirect.stderrToStdout);
    }

    ~this () {
        if (! ps.pid.tryWait.terminated) {
            ps.pid.kill ();
        }
    }

    string [] readlines () {
        string lines;
        string line;
        char [bufsize] buffer;

        try {
            int loop = 16;

            while (loop -- > 0 && ps.stdout.hasData) {
                line = cast (string) ps.stdout.rawRead (buffer);

                if (! line.empty) {
                    lines ~= line;
                }
            }
        }
        catch (Exception e) {
            "Exception: %s".writeln (e);
        }
        return lines.splitLines ();
    }
}


void main () {

    NonBlockingPs ps = NonBlockingPs ("bash", "-c", `
        for i in {1..10}; do
            printf "hello %02d" $i
            sleep 1
        done
    `);

    while (! ps.pid.tryWait.terminated) {
        string [] text = ps.readlines ();

        if (text.empty) {
            "Nothing to read for now".writeln;
        }
        else {
            "=> %s".writefln (text.join ("\n => "));
        }
        Thread.getThis ().sleep (500.dur!"msecs");
    }
}
--------------------------------------------------

And here is the output of its execution (launched with `dub nbio.d` -- as I named the file `nbio.d`):

Nothing to read for now
=> hello 01
Nothing to read for now
=> hello 02
Nothing to read for now
=> hello 03
Nothing to read for now
=> hello 04
Nothing to read for now
=> hello 05
Nothing to read for now
=> hello 06
Nothing to read for now
=> hello 07
Nothing to read for now
=> hello 08
Nothing to read for now
=> hello 09
Nothing to read for now
=> hello 10
Nothing to read for now


November 14, 2018
On Tuesday, 13 November 2018 at 13:52:57 UTC, Sobaya wrote:
> But I don't know how many lines are sent from the server for an input, so readln function blocks.

Read lines in another thread and send them to the main thread with std.concurrency.