tags:

views:

519

answers:

6

I'm trying to find out if a child process is waiting for user input (without parsing its output). Is it possible, in C on Unix, to determine if a pipe's read end currently has a read() call blocking?

A: 

If I recall correctly, you can not have a pipe with no reader which means that you have either a read(2) or a select(2) syscal pending at all time.

Keltia
That's not really true, you can have a pipe without reader. And "having reader" means "there is a process that has the pipe open()-ed for reading", it doesn't have anything to do with select() or read().
jpalecek
Agree with jpalecek.
Jonathan Leffler
A: 

I don't think that's true: For example, right before calling read() on the reader side, the pipe would have a reader that isn't actually reading.

A: 

You would typically just write to the pipe, or use select or poll. If you need a handshake mechanism you can do that out of band various ways or come up with and in-band protocol.

I don't know if there is a built-in way to know if a reader on the other end is blocking. Why do you need to know this?

robottobor
+1  A: 

The thing is, I have no control over the programs exec'd in the child processes. They print all kinds of verbose garbage which I would usually want to redirect to /dev/null. Occasionally though one will prompt the user for something. (With the prompt having no reliable format.) So my idea was:

  • In a loop:
    • Drain child's stdout, append it to a temporary buffer.
    • Check (no idea how) if the child is asking for user input, in which case the buffer is printed to stdout.
  • When the child exits, throw away the buffer.
The trouble is, then, that you've no real way to determine what to supply as input to the child, either. I'm not even sure that 'expect' can help - though it is pretty flexible about this sort of thing.
Jonathan Leffler
+1  A: 

You have these options:

  • if you know that the child will need certain input (such as shell that will read a command), just write to a pipe
  • if you assume the child won't read anything usually, but may do it sometimes, you probably need something like job control in the shell (use a terminal for communication with the child, use process groups and TIOCSPGRP ioctl on the terminal to get the child to the background; the child will get SIGTTIN when it tries to read from the terminal, and you can wait() for that). This is how bash handles things like "(sleep 10; read a;)&"
  • if you don't know what to write, or you have more possibilities, you will have to parse the output
jpalecek
+1  A: 

That sounds as if you were trying to supervise dpkg where occasionally some post-inst script queries the admin whether it may override some config file.

Anyway, you may want to look at how strace works:

strace -f -etrace=read your.program

Of course you need to keep track of which fds are the pipes you write about, but you probably need only stdin, anyway.

edgar.holleis