c - Pipestream and child processes -


i need write pipestream. program should names of programs , call them, first program should read stdin second output of first on. last program print result in stdout. problem doesn't work. when call program 2 simple programs (they both read x , print 2*x while can read), , give data suppose should result immediately, don't. more when give end of file doesn't react. don't pay attention on safe_* functions, same standart, check errors. me, please =)

#include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include "error.h" #include "safe_functions.h"  void call(const char *filename, int in_descr, int out_descr, pid_t *sons, int n) {     sons[n] = safe_fork();     if(sons[n] == 0)     {         safe_dup2(in_descr, stdin_fileno);         safe_dup2(out_descr, stdout_fileno);          safe_execv(filename, (char **)null);     } }  int find_num(pid_t * sons, int n, pid_t id) {     for(int i=0; i<n; i++)         if(sons[i] == id)             return i;      return -1; }  int main(int argc, const char ** argv) {      int **descr;     descr = (int**)safe_malloc(argc*sizeof(int*));     for(int i=0; i<argc; i++)         descr[i] = (int*) safe_malloc(2*sizeof(int));      for(int i=1; i+1<argc; i++)         safe_pipe(descr[i]);      descr[0][0] = 0;     descr[argc-1][1] = 1;      pid_t *sons = safe_malloc((argc-1) * sizeof(pid_t));      for(int i=1; i<argc; i++)         call(argv[i], descr[i-1][0], descr[i][1], sons, i-1);      int status;     pid_t id;     while(1)     {         id = safe_wait(&status);         if(id == -1)             break;          if(wifexited(status))         {             int num = find_num(sons, argc-1, id);             safe_close(descr[num][0]);             safe_close(descr[num+1][1]);             continue;         }          if(wifsignaled(status))         {             int num = find_num(sons, argc-1, id);             fatal_error("process teminated signal", argv[num+1], wexitstatus(status));         }     }      free(sons);     for(int i=0; i<argc; i++)         free(descr[i]);     free(descr); } 

you have near enough calls close()! parent must close copies of pipes. after duplicating relevant pipe descriptors standard input , output, children must close every pipe descriptor too. otherwise, processes never eof because there's process write pipes.

an sscce (short, self-contained, correct example)

this code uses stderr.h , stderr.c code in place of error.h (contact me if want code — see profile). writes out safe_* functions — or, @ least, implementation of them.

the dump_fds() function reports on file descriptors open in range 0-19, sufficient , programs; more complex version works sysconf() determine number of file descriptors check, number vastly greater (eg 256 or larger) number in use. use simple way check file descriptors should closed closed.

there considerable debug output. call execv() provides proper argument list.

#include <assert.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h>  //#include "error.h" //#include "safe_functions.h"  #include "stderr.h"  extern pid_t safe_fork(void); extern void  safe_dup2(int old_fd, int new_fd); extern void  safe_execv(const char *prog, char **argv); extern void  safe_pipe(int *pipe_fds); extern void *safe_malloc(size_t size); extern int   safe_wait(int *status); extern void  safe_close(int fd);  /* report on open file descriptors (0..19) in process */ static void dump_fds(void) {     struct stat b;     char buffer[32];     sprintf(buffer, "%d: ", getpid());     char *str = buffer + strlen(buffer);     (int = 0; < 20; i++)         *str++ = (fstat(i, &b) == 0) ? 'o' : '-';     *str++ = '\n';     *str = '\0';     fputs(buffer, stderr); }  static void close_pipes(int **descr, int argc) {     (int = 0; < argc; i++)     {         (int j = 0; j < 2; j++)         {             if (descr[i][j] > 1)             {                 err_remark("close %d\n", descr[i][j]);                 safe_close(descr[i][j]);             }         }     } }  static void call(char *filename, int in_descr, int out_descr, pid_t *sons, int n, int **descr, int argc) {     sons[n] = safe_fork();     if (sons[n] == 0)     {         err_remark("call: %s\n", filename);         char *argv[2] = { filename, null };         err_remark("dup2(%d, %d)\n", in_descr, stdin_fileno);         err_remark("dup2(%d, %d)\n", out_descr, stdout_fileno);         safe_dup2(in_descr, stdin_fileno);         safe_dup2(out_descr, stdout_fileno);         close_pipes(descr, argc);         dump_fds();         safe_execv(argv[0], argv);     } }  static int find_num(pid_t *sons, int n, pid_t id) {     (int i=0; i<n; i++)     {         if (sons[i] == id)             return i;     }     return -1; }  int main(int argc, char **argv) {     err_setarg0(argv[0]);     err_setlogopts(err_pid);     dump_fds();      int **descr;     descr = (int**)safe_malloc(argc*sizeof(int*));      (int i=0; i<argc; i++)         descr[i] = (int*) safe_malloc(2*sizeof(int));      (int i=1; i+1<argc; i++)         safe_pipe(descr[i]);      descr[0][0] = 0;     descr[argc-1][1] = 1;      pid_t *sons = safe_malloc((argc-1) * sizeof(pid_t));      (int i=1; i<argc; i++)     {         err_remark("command: %s\n", argv[i]);         call(argv[i], descr[i-1][0], descr[i][1], sons, i-1, descr, argc);     }      close_pipes(descr, argc);      while (1)     {         int status;         pid_t id = safe_wait(&status);         err_remark("wait: pid %d, status 0x%.4x\n", (int)id, status);          if (id == -1)             break;          if (wifexited(status))         {             int num = find_num(sons, argc-1, id);             //safe_close(descr[num][0]);             //safe_close(descr[num+1][1]);             continue;         }          if (wifsignaled(status))         {             int num = find_num(sons, argc-1, id);             err_remark("process %s terminated signal %d", argv[num+1], wexitstatus(status));         }     }      free(sons);     (int i=0; i<argc; i++)         free(descr[i]);     free(descr);      return(0); }   extern pid_t safe_fork(void) {     pid_t pid = fork();     if (pid < 0)         err_syserr("failed fork() ");     return pid; }  extern void safe_dup2(int old_fd, int new_fd) {     if (dup2(old_fd, new_fd) < 0)         err_syserr("failed dup2(%d, %d) ", old_fd, new_fd); }  extern void safe_execv(const char *prog, char **argv) {     execv(prog, argv);     err_syserr("failed execv(\"%s\") ", prog); }  extern void safe_pipe(int *pipe_fds) {     assert(pipe_fds != 0);     if (pipe(pipe_fds) != 0)         err_syserr("failed pipe() ");     err_remark("pipe: %d, %d\n", pipe_fds[0], pipe_fds[1]); }  extern void *safe_malloc(size_t size) {     void *vp = malloc(size);     if (vp == 0)         err_syserr("out of memory ");     return vp; }  extern int safe_wait(int *status) {     assert(status != 0);     return wait(status); }  extern void safe_close(int fd) {     if (close(fd) < 0)         err_syserr("failed close(%d)\n", fd); } 

example output

$ ./pipes-15845060 /bin/ps /usr/bin/sort /bin/cat 12096: ooo----------------- pipes-15845060: pid=12096: pipe: 3, 4 pipes-15845060: pid=12096: pipe: 5, 6 pipes-15845060: pid=12096: command: /bin/ps pipes-15845060: pid=12096: command: /usr/bin/sort pipes-15845060: pid=12096: command: /bin/cat pipes-15845060: pid=12096: close 3 pipes-15845060: pipes-15845060: pid=12098: pid=12096: close 4 pipes-15845060: pid=12096: close 5 pipes-15845060: pid=12096: close 6 call: /bin/ps pipes-15845060: pid=12098: dup2(0, 0) pipes-15845060: pid=12098: dup2(4, 1) pipes-15845060: pid=12099: call: /usr/bin/sort pipes-15845060: pid=12099: dup2(3, 0) pipes-15845060: pid=12099: dup2(6, 1) pipes-15845060: pid=12098: pipes-15845060: pid=12099: close 3 pipes-15845060: pid=12099: close 4 pipes-15845060: pid=12099: close 5 pipes-15845060: pid=12099: close 6 12099: ooo----------------- close 3 pipes-15845060: pid=12098: close 4 pipes-15845060: pid=12098: close 5 pipes-15845060: pid=12098: close 6 12098: ooo----------------- pipes-15845060: pid=12100: call: /bin/cat pipes-15845060: pid=12100: dup2(5, 0) pipes-15845060: pid=12100: dup2(1, 1) pipes-15845060: pid=12100: close 3 pipes-15845060: pid=12100: close 4 pipes-15845060: pid=12100: close 5 pipes-15845060: pid=12100: close 6 12100: ooo----------------- pipes-15845060: pid=12096: wait: pid 12098, status 0x0000   563 ttys000    0:00.03 -sh   568 ttys001    0:00.03 -sh   578 ttys003    0:00.03 -sh   587 ttys002    0:00.03 -sh   588 ttys005    0:00.15 -sh   589 ttys004    0:00.20 -sh   pid tty           time cmd 12096 ttys004    0:00.00 ./pipes-15845060 /bin/ps /usr/bin/sort /bin/cat 12097 ttys004    0:00.00 sed /./s/^/    / 12099 ttys004    0:00.00 /usr/bin/sort 12100 ttys004    0:00.00 /bin/cat pipes-15845060: pid=12096: wait: pid 12100, status 0x0000 pipes-15845060: pid=12096: wait: pid 12099, status 0x0000 pipes-15845060: pid=12096: wait: pid -1, status 0x0000 $ 

Comments

Popular posts from this blog

monitor web browser programmatically in Android? -

Shrink a YouTube video to responsive width -

wpf - PdfWriter.GetInstance throws System.NullReferenceException -