www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Detect that a child is waiting for input

reply unDEFER <undefer gmail.com> writes:
Hello!
I'm using pipeProcess() to create a process:

pipes = pipeProcess(["bash", "-c", BASH_COMMAND], Redirect.stdin 
| Redirect.stdout | Redirect.stderr);

Is it possible detect that the child is waiting for input on 
stdin?
I can't find decision even for C. I think it is impossible if the 
child uses unblocking reading. But I want to detect blocking 
reading.
Nov 20 2016
next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Sunday, 20 November 2016 at 12:21:19 UTC, unDEFER wrote:
 Hello!
 I'm using pipeProcess() to create a process:

 pipes = pipeProcess(["bash", "-c", BASH_COMMAND], 
 Redirect.stdin | Redirect.stdout | Redirect.stderr);

 Is it possible detect that the child is waiting for input on 
 stdin?
 I can't find decision even for C. I think it is impossible if 
 the child uses unblocking reading. But I want to detect 
 blocking reading.
If blocking is an error, you could close stdin and assuming the process checks the error codes correctly....
Nov 20 2016
parent reply unDEFER <undefer gmail.com> writes:
On Sunday, 20 November 2016 at 21:03:57 UTC, John Colvin wrote:
 If blocking is an error, you could close stdin and assuming the 
 process checks the error codes correctly....
No, I mean blocking is not error. One method to find it, run gdb or strace and see where the process stopped, or which syscall was last. But I believe that must be other way.
Nov 20 2016
parent reply wobbles <grogan.colin gmail.com> writes:
On Monday, 21 November 2016 at 07:29:55 UTC, unDEFER wrote:
 On Sunday, 20 November 2016 at 21:03:57 UTC, John Colvin wrote:
 If blocking is an error, you could close stdin and assuming 
 the process checks the error codes correctly....
No, I mean blocking is not error. One method to find it, run gdb or strace and see where the process stopped, or which syscall was last. But I believe that must be other way.
Easier said than done as there's no signal the child sends to say "OK, I'm waiting now". You can use expect to do this, if you know what the output of the child will be just before it's waiting for IO. This is the D lib I've written to do this: https://github.com/grogancolin/dexpect It's not wonderful or anything, but it works :)
Nov 22 2016
parent reply unDEFER <undefer gmail.com> writes:
On Tuesday, 22 November 2016 at 22:30:06 UTC, wobbles wrote:
 Easier said than done as there's no signal the child sends to 
 say "OK, I'm waiting now".

 You can use expect to do this, if you know what the output of 
 the child will be just before it's waiting for IO.

 This is the D lib I've written to do this:
 https://github.com/grogancolin/dexpect

 It's not wonderful or anything, but it works :)
Thank you, good decision. Maybe I will use the idea. But how to detect that "cat" (without arguments) waits input, if it nothing prints?
Nov 23 2016
parent reply wobbles <grogan.colin gmail.com> writes:
On Wednesday, 23 November 2016 at 15:54:30 UTC, unDEFER wrote:
 On Tuesday, 22 November 2016 at 22:30:06 UTC, wobbles wrote:
 Easier said than done as there's no signal the child sends to 
 say "OK, I'm waiting now".

 You can use expect to do this, if you know what the output of 
 the child will be just before it's waiting for IO.

 This is the D lib I've written to do this:
 https://github.com/grogancolin/dexpect

 It's not wonderful or anything, but it works :)
Thank you, good decision. Maybe I will use the idea. But how to detect that "cat" (without arguments) waits input, if it nothing prints?
You dont :) You could wait for some period of time - and if that's passed and the child hasn't printed anything you can assume it's waiting for input.
Nov 23 2016
parent unDEFER <undefer gmail.com> writes:
On Wednesday, 23 November 2016 at 20:02:08 UTC, wobbles wrote:
 You could wait for some period of time - and if that's passed 
 and the child hasn't printed anything you can assume it's 
 waiting for input.
Yes, I also have thought about it, thank you.
Nov 23 2016
prev sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 20/11/16 14:21, unDEFER wrote:
 Hello!
 I'm using pipeProcess() to create a process:

 pipes = pipeProcess(["bash", "-c", BASH_COMMAND], Redirect.stdin |
 Redirect.stdout | Redirect.stderr);

 Is it possible detect that the child is waiting for input on stdin?
 I can't find decision even for C. I think it is impossible if the child
 uses unblocking reading. But I want to detect blocking reading.
The shell does that for background processes. I think it takes away the TTY from its children, and this way, when they try to read from stdin, they get SIGSTOP from the system. I'm not sure what the precise mechanism is. There are flags passed to wait which will cause it to report when a child gets SIGSTOP. Hope this helps, Shachar
Nov 22 2016
next sibling parent unDEFER <undefer gmail.com> writes:
On Wednesday, 23 November 2016 at 07:18:27 UTC, Shachar Shemesh 
wrote:
 The shell does that for background processes. I think it takes 
 away the TTY from its children, and this way, when they try to 
 read from stdin, they get SIGSTOP from the system.

 I'm not sure what the precise mechanism is.

 There are flags passed to wait which will cause it to report 
 when a child gets SIGSTOP.

 Hope this helps,
 Shachar
Really interesting information, thank you, I will try to dig in this direction.
Nov 23 2016
prev sibling parent reply unDEFER <undefer gmail.com> writes:
On Wednesday, 23 November 2016 at 07:18:27 UTC, Shachar Shemesh 
wrote:

 The shell does that for background processes. I think it takes 
 away the TTY from its children, and this way, when they try to 
 read from stdin, they get SIGSTOP from the system.

 I'm not sure what the precise mechanism is.

 There are flags passed to wait which will cause it to report 
 when a child gets SIGSTOP.

 Hope this helps,
 Shachar
So, I have found with strace, this signal is SIGTTIN is special signal which sends to _background_ task when it tries to read from terminal. So it is possible such detect when I will write not simple pipeProcess, but will write terminal emulator. Thank you.
Nov 24 2016
next sibling parent reply unDEFER <undefer gmail.com> writes:
Here is good information about difference between foreground 
process groups and background:
https://www.win.tue.nl/~aeb/linux/lk/lk-10.html

Shortly, there is only one process group which is foreground, you 
can get it with tcgetpgrp(fd) or set it with tcsetpgrp(fd,pgrp). 
To setup process group of the process use setpgid(pid, pgid);
Nov 24 2016
parent reply unDEFER <undefer gmail.com> writes:
The program which stops even run without "&":

#!/usr/bin/rdmd
import std.stdio;
import std.file;
import std.string;

import core.sys.posix.unistd;
import core.stdc.errno;
import core.stdc.string;

void main()
{
     int res = core.sys.posix.unistd.tcsetpgrp(0, getppid());
     if (res != 0)
     {
         writefln("tcsetpgrp error: %s", 
fromStringz(strerror(errno)).idup());
         return;
     }

     foreach (line; stdin.byLine)
     {
         writefln(line);
     }
}


But really it is not decision.. The program stops not because 
where is no input, but because there is other process reading 
terminal..
It is not that I need..
Nov 24 2016
parent Shachar Shemesh <shachar weka.io> writes:
On 24/11/16 17:58, unDEFER wrote:

 But really it is not decision.. The program stops not because where is
 no input, but because there is other process reading terminal..
 It is not that I need..
You can write a wrapper program (let's call it wrp). Wrp can redirect your program's input though itself, and play with the session foreground based on whether there is input pending or not. This way, your program will stop if the combination of two things happen: 1. It is waiting for input and 2. There is none This is, I think, what you want.
Nov 25 2016
prev sibling parent Shachar Shemesh <shachar weka.io> writes:
You can detect whether another process received a signal by ptracing it. 
If you are only ptracing for signals, then the performance penalty 
shouldn't be too severe.

Shachar

On 24/11/16 12:35, unDEFER wrote:
 On Wednesday, 23 November 2016 at 07:18:27 UTC, Shachar Shemesh wrote:

 The shell does that for background processes. I think it takes away
 the TTY from its children, and this way, when they try to read from
 stdin, they get SIGSTOP from the system.

 I'm not sure what the precise mechanism is.

 There are flags passed to wait which will cause it to report when a
 child gets SIGSTOP.

 Hope this helps,
 Shachar
So, I have found with strace, this signal is SIGTTIN is special signal which sends to _background_ task when it tries to read from terminal. So it is possible such detect when I will write not simple pipeProcess, but will write terminal emulator. Thank you.
Nov 24 2016