Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You need, as I answered in a <a href="https://stackoverflow.com/a/20571668/841108">related answer</a> to a previous question by you, to implement an <a href="https://en.wikipedia.org/wiki/Event_loop" rel="nofollow noreferrer">event loop</a>; as it name implies, it is <em>looping</em>, so you should code in the parent process:</p> <pre><code>while (1) { // simplistic event loop! int status=0; if (waitpid(pid, &amp;status, WNOHANG) == pid) { // clean up, child process has ended handle_process_end(status); break; }; struct pollpfd pfd[2]; memset (&amp;pfd, 0, sizeof(pfd)); // probably useless but dont harm pfd[0].fd = rpipe[0]; pfd[0].events = POLL_IN; pfd[1].fd = wpipe[1]; pfd[0].event = POLL_OUT; #define DELAY 5000 /* 5 seconds */ if (poll(pfd, 2, DELAY)&gt;0) { if (pfd[0].revents &amp; POLL_IN) { /* read something from rpipe[0]; detect end of file; you probably need to do some buffering, because you may e.g. read some partial line chunk written by the child, and you could only handle full lines. */ }; if (pfd[1].revents &amp; POLL_OUT) { /* write something on wpipe[1] */ }; } fflush(NULL); } /* end while(1) */ </code></pre> <p>you cannot predict in which order the pipes are readable or writable, and this can happen many times. Of course, a lot of buffering (in the parent process) is involved, I leave the details to you.... You have no influence on the buffering in the child process (some programs detect that their output is or not a terminal with <a href="http://pubs.opengroup.org/onlinepubs/009604599/functions/isatty.html" rel="nofollow noreferrer">isatty</a>).</p> <p>What an <em>event polling loop</em> like above gives you is to avoid the deadlock situation where the child process is blocked because its stdout pipe is full, while the parent is blocked writing (to the child's stdin pipe) because the pipe is full: with an event loop, you read as soon as some data is polled readable on the input pipe (i.e. the stdout of the child process), and you write some data as soon as the output pipe is polled writable (i.e. is not full). You cannot predict in advance in which order these events "output of child is readable by parent" and "input of child is writable by parent" happen.</p> <p>I recommend reading <a href="http://advancedlinuxprogramming.com/" rel="nofollow noreferrer">Advanced Linux Programming</a> which has several chapters explaining these issues!</p> <p>BTW my simplistic event loop is a bit wrong: if the child process terminated and some data remains in its stdout pipe, its reading is not done. You could move the <code>waitpid</code> test after the <code>poll</code></p> <p>Also, don't expect that a single <code>write</code> (from the child process) into a pipe would trigger one single <code>read</code> in the parent process. In other words, there is no notion of message length. However, POSIX knows about <code>PIPE_MAX</code> .... See its <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html" rel="nofollow noreferrer">write</a> documentation. Probably your buffer passed to <code>read</code> and <code>write</code> should be of <code>PIPE_MAX</code> size.</p> <p>I repeat: you need to <strong>call <code>poll</code> inside your event <em>loop</em></strong> and very probably <code>poll</code> will be called <em>several times</em> (because your loop will be repeated many times!), and will report readable or writable pipe ends in an unpredictable (and non-reproducible) order! A first run of your program could report "<code>rpipe[0]</code> readable", you <code>read</code> 324 bytes from it, you repeat the event loop, <code>poll</code> says you "<code>wpipe[1]</code> writable", you can <code>write</code> 10 bytes to it, you repeat the event loop, <code>poll</code> tells that "<code>rpipe[0]</code> readable", you <code>read</code> 110 bytes from it, you repeat the event loop, <code>poll</code> tells again "<code>rpipe[0]</code> readable", you <code>read</code> 4096 bytes from it, etc etc etc... A second run of the same program in the same environment would give different events, like: <code>poll</code> says that "<code>wpipe[1]</code> writable", you <code>write</code> 1000 bytes to it, you repeat the loop, <code>poll</code> says that "<code>rpipe[0]</code> readable, etc....</p> <p>NB: your issue is not the buffering in the child ("client") program, which we assume you cannot change. So what matters is not the buffered data in it, but the <em>genuine</em> input and output (that is the only thing your parent process can observe; internal child buffering is irrelevant for the parent), i.e. the data that your child program has been able to <em>really</em> <a href="http://man7.org/linux/man-pages/man2/read.2.html" rel="nofollow noreferrer">read(2)</a> and <a href="http://man7.org/linux/man-pages/man2/write.2.html" rel="nofollow noreferrer">write(2)</a>. And if going thru a <a href="http://man7.org/linux/man-pages/man7/pipe.7.html" rel="nofollow noreferrer">pipe(7)</a>, such data will become <a href="http://man7.org/linux/man-pages/man2/poll.2.html" rel="nofollow noreferrer">poll(2)</a>-able in the parent process (and your parent process can <code>read</code> or <code>write</code> some of it after <code>POLL_IN</code> or <code>POLL_OUT</code> in the updated <code>revents</code> field after <code>poll</code>). BTW, if you did code the child, don't forget to call <code>fflush</code> at appropriate places inside it.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload