problems with FORK() and WAITPID()


 
Thread Tools Search this Thread
Top Forums Programming problems with FORK() and WAITPID()
# 1  
Old 07-13-2005
problems with FORK() and WAITPID()

Dear All,

I'm trying to write multithreading TCP Daemon which executes external program when new network connection arrives on a socket.
After accept() I'm doing fork() for initiating of new child process, in which will be executed external program. After child creation I'm doing fork() again, and substitute context of new child process using execv() with context of external program. In the body of parent code I'm doing waitpid() for expectation of finishing of child process. Waitpid() always returns -1 with error code errno=ECHILD (No child processes).
Testing this code without _first_ fork(), everything works perfectly.
May be somebody knows how it should be done? Is it possible to use fork() few times to create child processes and wait finish them into parents by waitpid() ?
Here is code of external program excecution:
Code:
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <string.h> 
#include <signal.h> 
#include <errno.h> 
#include <setjmp.h> 
#define MAX_EPRG_ARGS   10 
#define MAX_LEN   5000 
#define EXT_PRG_TIMEOUT   30 /* Seconds */ 
/* For signal processing */ 
pid_t pid_to_kill   = (-1); 
jmp_buf env; 
void sig_alrm (int dummy) 
{ 
if (pid_to_kill>0) 
  { 
   kill (pid_to_kill,9); /* Kill it */ 
   longjmp (env,1); 
  } 
} 
int execute (char * ext_prg, 
char * ext_arg, 
char * ext_output, 
size_t bufsize) 
{ 
  int rcode = -1; 
  int Pipe [2]; 
  int status = 0; 
  char * ARGUMENTS [MAX_EPRG_ARGS]; 
  char temp_str [5000]; 
  int i=0; 
  int ret_wpd = -1; 
  char data [2]; 
  sig_t prev; 
  /* Clear the buffer */ 
  memset (ext_output,0,bufsize); 
  prev=signal (SIGALRM,sig_alrm); 
  if (setjmp(env)!=0) 
  { 
   /* Here returns longjmp */ 
   if (pid_to_kill>0) 
   { 
    /* Return the prev sigaction */ 
    signal (SIGALRM,prev); 
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): Timeout waiting external program termination, killing pid: %lu",pid_to_kill); 
    write_log (temp_str); 
    close (Pipe[0]); 
    close (Pipe[1]); 
    return (-1); 
   } 
  } 
  if (pipe(Pipe)==-1) 
   { 
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): Cannot create pipe: '%s' !\n",strerror(errno)); 
    write_log (temp_str); 
    return (-1); 
   } 

  memset (&temp_str,0,sizeof(temp_str)); 
  if ((rcode=fork ())==0)  /* Child */ 
   { 
    for (i=0;i<=MAX_EPRG_ARGS-1;i++) ARGUMENTS[i]=NULL; 
    ARGUMENTS[0]=ext_prg; 
    ARGUMENTS[1]=strtok (ext_arg, " \t");     
    if (ARGUMENTS[1]!=NULL) 
     { 
       for (i=2;i<=MAX_EPRG_ARGS-1;i++) 
        { 
         ARGUMENTS[i]=strtok (NULL, " \t");     
         if (ARGUMENTS[i]==NULL) break; 
        } 
     } 
    /* First close the read end of the pipe */ 
    close (Pipe[0]);     
    /* Make a dup */ 
    if (dup2(Pipe[1],1)==-1) 
     { 
      snprintf (temp_str,sizeof(temp_str)-1,"execute(): 'Dup2' command failed: '%s' !\n",strerror(errno)); 
      write_log (temp_str); 
      close (Pipe[0]); 
      close (Pipe[1]); 
      exit (253); 
     } 
     
    if (execv(ext_prg,ARGUMENTS)==-1) 
     { 
      snprintf (temp_str,sizeof(temp_str)-1,"execute(): Cannot execute external programm: '%s', Error: '%s' !\n",ext_prg,strerror(errno)); 
      write_log (temp_str); 
      close (Pipe[0]); 
      close (Pipe[1]); 
      exit (253); /* Parent will get return status: 253 */ 
     } 
    close (Pipe[1]); 
   } 
   
  if (rcode==-1)  /* Parent */ 
   { 
    snprintf  (temp_str,sizeof(temp_str)-1,"execute(): 'Fork' command failed: '%s' !\n",strerror(errno)); 
    write_log (temp_str); 
    close (Pipe[0]); 
    close (Pipe[1]); 
    return -1; 
   } 
  /* Prepare for signal processing */ 
  pid_to_kill=rcode; 
   
  alarm (EXT_PRG_TIMEOUT); 

  if (waitpid (rcode,&status, (WUNTRACED))==-1) 
   { 
    snprintf (temp_str,sizeof(temp_str)-1,"execute(): 'Waitpid' command failed: '%s' !\n",strerror(errno)); 
    write_log (temp_str); 
    close (Pipe[0]); 
    close (Pipe[1]); 
    return -1; 
   } 

  /* First close the write end of the pipe */ 
  close (Pipe[1]);     
  memset (&data,0,sizeof(data)); 
  while (read(Pipe[0],data,1)>0) 
  { 
   if (strlen(ext_output)<(bufsize-1)) strcat (ext_output,data); 
   memset (&data,0,sizeof(data)); 
  } 
  alarm (0); /* Stop the timer */ 
   
  signal (SIGALRM,prev); /* Return the prev sigaction */ 
  if (WIFEXITED(status)) 
   { 
    rcode=WEXITSTATUS (status); 
    if (rcode==253) goto L1; 
    else 
    { 
     close (Pipe[0]); 
     return (rcode); 
    } 
   } 
L1: 
  snprintf (temp_str,sizeof(temp_str)-1,"execute(): Abnormal child termination !\n"); 
  write_log (temp_str); 
  close (Pipe[0]); 
  close (Pipe[1]); 
  return -1; 
}

This code perfectly works if execute() called within first fork(). But doing another fork() causes waipid retun -1 and errno set to ECHILD.

Nowhere SIGCHLD handler is redefined.

P.S Operational System is FreeBSD 5.3

Last edited by Perderabo; 07-13-2005 at 01:40 PM.. Reason: Add code tags for readability
# 2  
Old 07-13-2005
grandchild != child
When your child dies its children are adopted by init. A process cannot wait for a grandchild.
# 3  
Old 07-13-2005
Quote:
Originally Posted by Perderabo
grandchild != child
When your child dies its children are adopted by init. A process cannot wait for a grandchild.
OK. I agree ... But:

Process1->(fork())->Process2->(fork())->Process3->execv()->NewProgram

Process2 is a child for Process1. Process3 is a child for Process2. I do waitpid in Process2 that waits for Process3 finishing. I do not try to wait for grandchild. I try to waitpid in parent process and wait for child finishing.

May be I do something wrong ?
# 4  
Old 07-13-2005
This can be caused by setting SA_NOCLDWAIT for SIGCHLD or explicitly ignoring SIGCHLD. Do you do either? I am strictly a structured progrommer so I don't have much experience with goto's or longjmp. Consequently, I don't know what happens when you longjmp out of a signal handler. I thought that the rule was longjmp within a handler, but siglongjmp out.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

waitpid and grandchildren

I'm attempting to write a daemon that will start, stop, and monitor processes across a network of servers, meaning that a daemon would start on each server, attempt to connect to siblings at regular intervals (if there are unconnected siblings), and start services as remote dependencies are... (3 Replies)
Discussion started by: kshots
3 Replies

2. Programming

[C]Fork and waitpid

Hi folks, I am writing a simple program to understand how fork() and waitpid works, but it doesn't seem that is working like I wanted. if(fork()==0){ //el hijo pid1=getpid(); printf("\nSoy el hijo %d",pid1); }else { //el padre if (fork()==0) { //el hijo pid2=getpid();... (2 Replies)
Discussion started by: lamachejo
2 Replies

3. Programming

waiting for multiple childs - C - waitpid

Hi gurus, I would like to fork more children and then write their return values: so far I tried: #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(void) { pid_t pid; int rv=0, i; ... (5 Replies)
Discussion started by: wakatana
5 Replies

4. Programming

Fork()

does fork() spawn only the parent process, what if fork() is looped, does it spawn the parent and the child? (4 Replies)
Discussion started by: Peevish
4 Replies

5. Programming

Problems with child comunicating with parent on fork()

Hello, I'm trying to implement a version of a bucketSort (kinda) server/client, but I'm having a VERY hard time on making the server behave correctly, when talking to the children, after it forks. The server is kinda big (300+ lines), so I won't post it here, but here's what I'm doing. 1)create a... (8 Replies)
Discussion started by: Zarnick
8 Replies

6. Programming

problems with fork() inheritating

Hi, thanks for any ideas... in main() i wrote this code: ... for(i=0;i<10;i++){ pid=fork(); switch(pid){ case -1 printf("error"); case 0:child(); default:waitpid(pid,NULL,0); } } ... void child(){ SOMETHING; } (4 Replies)
Discussion started by: michael26100
4 Replies

7. Programming

Fork ()

hi all About this code for (i = 1; i < n; i++) if ((childpid = fork()) <= 0) break; I really can't understand the output . and the way fork () return the value . how about the process Id ,the child process Id and the parent ID in this case so please answer me soon (5 Replies)
Discussion started by: iwbasts
5 Replies

8. Programming

Fork or what?

Hello all. I'm developing a filetransfer application, which is supposed to work sort of like dcc, with multiple transfers etc. Now i wonder what the best way to manage the transfers is. Should i fork() for each new transfer, hogging loads of memory or use pthreads? Maybe I can use select to see... (0 Replies)
Discussion started by: crippe
0 Replies

9. Programming

fork()

#include <stdio.h> #include <string.h> #include <sys/types.h> #define MAX_COUNT 200 #define BUF_SIZE 100 void main(void) { pid_t pid; int i; char buf; fork(); pid = getpid(); for (i = 1; i <= MAX_COUNT; i++) { sprintf(buf,... (2 Replies)
Discussion started by: MKSRaja
2 Replies

10. Programming

fork() fd

I run this code, actually I want to both processes print the message from "data". But only one does. What happens? Anyone can help? #include <stdio.h> main(){ int fd, pid; char x; fd = open("data",0); /* open file "data" */ pid = fork(); if(pid != 0){ wait(0); ... (2 Replies)
Discussion started by: Herman
2 Replies
Login or Register to Ask a Question