|
Home > Archive > Unix Programming > June 2006 > reading other user's output
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
reading other user's output
|
|
| khanzf@gmail.com 2006-06-11, 1:23 am |
| I'm writing a program which will read the stdout output of another
program. I do this by creating a pipe, then working, then in the child
process, dup2'ing the stdout onto the pipe and calling execl to execute
the program. The parent in the mean time read()'s from the pipe in a
loop Here is my code
The problem is that the loop with read() from the pipe forever. How do
I make it stop after the program child process dies?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
int filedes[2];
int pid;
if (pipe(filedes) == -1) {
perror("error in pipe");
exit(1);
}
pid = fork();
if (pid == 0) {
dup2(filedes[1], fileno(stdout));
execl("output", "output", NULL);
}
else if (pid) {
char c;
int len;
do {
len = read(filedes[0], &c, 1);
printf("--> %c\n", c);
} while (len);
exit(1);
}
}
| |
| Jolting 2006-06-11, 7:24 am |
| The parent will get a SIGCHLD signal when the child process exits. This
is typically used to get rid of zombie processes. If you don't flush
them they don't go away by themselves, but thats another story.
void handler(int signum){
exit(0);
}
then in main register the handler
signal(SIGCHLD,&handler);
simple as pie
khanzf@gmail.com wrote:
> I'm writing a program which will read the stdout output of another
> program. I do this by creating a pipe, then working, then in the child
> process, dup2'ing the stdout onto the pipe and calling execl to execute
> the program. The parent in the mean time read()'s from the pipe in a
> loop Here is my code
>
> The problem is that the loop with read() from the pipe forever. How do
> I make it stop after the program child process dies?
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/types.h>
>
> int main() {
> int filedes[2];
> int pid;
>
> if (pipe(filedes) == -1) {
> perror("error in pipe");
> exit(1);
> }
>
> pid = fork();
>
> if (pid == 0) {
> dup2(filedes[1], fileno(stdout));
> execl("output", "output", NULL);
> }
>
> else if (pid) {
> char c;
> int len;
>
> do {
> len = read(filedes[0], &c, 1);
> printf("--> %c\n", c);
> } while (len);
> exit(1);
>
> }
> }
| |
| khanzf@gmail.com 2006-06-11, 7:24 am |
| i added in child-signal catching, but that itself might not necessarily
work. That would only work if the child process only died BEFORE I
call read(), which isn't necessarily the case. That would be
problematic with smaller programs executed by execl(). the child
signal handler might be called BEFORE it has a change to read all the
data over the pipe.
- Farhan
Jolting wrote:[vbcol=seagreen]
> The parent will get a SIGCHLD signal when the child process exits. This
> is typically used to get rid of zombie processes. If you don't flush
> them they don't go away by themselves, but thats another story.
>
> void handler(int signum){
> exit(0);
> }
>
> then in main register the handler
>
> signal(SIGCHLD,&handler);
>
> simple as pie
>
> khanzf@gmail.com wrote:
| |
| Hubble 2006-06-11, 1:27 pm |
| khanzf@gmail.com schrieb:
> I'm writing a program which will read the stdout output of another
> program. I do this by creating a pipe, then working, then in the child
> process, dup2'ing the stdout onto the pipe and calling execl to execute
> the program. The parent in the mean time read()'s from the pipe in a
> loop Here is my code
>
> The problem is that the loop with read() from the pipe forever. How do
> I make it stop after the program child process dies?
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/types.h>
>
> int main() {
> int filedes[2];
> int pid;
>
> if (pipe(filedes) == -1) {
> perror("error in pipe");
> exit(1);
> }
>
> pid = fork();
>
> if (pid == 0) {
> dup2(filedes[1], fileno(stdout));
> execl("output", "output", NULL);
> }
>
> else if (pid) {
> char c;
> int len;
>
> do {
> len = read(filedes[0], &c, 1);
> printf("--> %c\n", c);
> } while (len);
> exit(1);
>
> }
> }
The problem here is not that you do not wait for SIGCHLD. On reception
of sigchld, you should call wait(2). You did not close the other ends
of the filedescriptor. So if your output process exits, filedes[0] is
still open by the parent process. You should call close(filedes[0])
before your read loop in the parent. Here is code which works on my
linux box:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
int filedes[2];
int pid;
if (pipe(filedes) == -1) {
perror("error in pipe");
exit(1);
}
pid = fork();
if (pid == 0) {
close(filedes[0]);
dup2(filedes[1], fileno(stdout));
execl("output", "output", NULL);
perror("output");
_exit(1);
}
else if (pid) {
char c;
int len;
close(filedes[1]); /* important to detect EOF */
do {
len = read(filedes[0], &c, 1);
printf("--> %c %d\n", c, len);
} while (len);
exit(1);
}
}
Hubble.
| |
| Francois Goudal 2006-06-12, 7:26 am |
| khanzf@gmail.com wrote:
> I'm writing a program which will read the stdout output of another
> program. I do this by creating a pipe, then working, then in the child
> process, dup2'ing the stdout onto the pipe and calling execl to execute
> the program. The parent in the mean time read()'s from the pipe in a
> loop Here is my code
>
> The problem is that the loop with read() from the pipe forever. How do
> I make it stop after the program child process dies?
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/types.h>
>
> int main() {
> int filedes[2];
> int pid;
>
> if (pipe(filedes) == -1) {
> perror("error in pipe");
> exit(1);
> }
>
> pid = fork();
>
> if (pid == 0) {
> dup2(filedes[1], fileno(stdout));
> execl("output", "output", NULL);
> }
>
> else if (pid) {
> char c;
> int len;
>
> do {
> len = read(filedes[0], &c, 1);
> printf("--> %c\n", c);
> } while (len);
> exit(1);
>
> }
> }
>
Maybe you should better take a look on the manpage of popen.
I think it will do exactly what you want, without bothering with fork,
dup2, etc...
--
Francois Goudal
Epita promo 2008 - Ing1 - President Evolutek
francois@goudal.net
|
|
|
|
|