Thread: create and listen to a process

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    29

    create and listen to a process

    (Using C on ubuntu)

    In my program I need to fork a process and execute a .bin in the child process. Then I want to create a pipe that "connects" the stdout of the child to the stdout of the parent. I know basically how to do this using write() and read() in the pipes.
    The problem is that the parent should wait until the child sends a specific message (a string), or until a timeout occurs. In the first case both processes should run in "parallel" ( I don't know if its the correct term..), in the second case the child must abort and the parent go on. And I don't have a clue how to accomplish any of this things. Any suggestions ?

    I made a very basic skeleton, comments?


    Code:
     int status;
        int fd[2]; /* pipe */
    
        if( pipe(fd) !=0 )
        {
          perror("Failed to create pipe");
          exit(EXIT_FAILURE);
        }
    
        pid_t pid=fork();
    
        if( pid<0)
        {
          perror("Failed to fork");
          exit(EXIT_FAILURE);
        }
    
        else if(pid == 0) /* child */
        {
          if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1);
          perror("Child unabled to start sixad");
    
          exit(EXIT_FAILURE);
        }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well reading a descriptor with a timeout is achieved by using the select() or poll() calls. These allow you to wait for something to arrive, or timeout if you choose.

    As for detecting the demise of the child (with it's exit status), then look at the waitpid() call. This too has a "poll" mechanism.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2010
    Posts
    29
    if I use waitpid(), the calling process suspends its course until the child has terminated, isn't that correct?

  4. #4
    Registered User
    Join Date
    Jun 2010
    Posts
    29
    I've the following question.

    Code:
     
       pid_t pid = fork();
      
       if(pid == 0) /* child */
        {
          if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1);
          {   
          perror("Child unabled to start sixad");
          exit(EXIT_FAILURE);
          }
          printf("here");
        }
    The message "here" is only printed when execl() has finished?

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    There is NO return is execl() is successful. You're running a different program after that point.

    Besides, your if statement has a very telling ; at the end of it.

    And how much manual page of waitpid did you actually read to miss WNOHANG ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Jun 2010
    Posts
    29
    Thank you for the answers. WNOHANG returns immediately if no child has exited, I don't want that. The idea is forking, suspend the parent and exec( a program I can't modify ).
    The exec program sends some messages to stdout and the parent should only continue after one specific message is received.

    I apologize for some naive questions but I'm an electronics student, not informatics. I don't have much knowledge about processes and OS's.

  7. #7
    Registered User
    Join Date
    Jun 2010
    Posts
    29
    When I fork() , the stdout and stdin are shared by both parent and child?

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by frs View Post
    When I fork() , the stdout and stdin are shared by both parent and child?
    yes. when you fork, the child process gets a copy of *ALL* open file descriptors, including sockets, message queues, shared memory segments, etc (some of these may be platform-dependent). you can close the child's stdout descriptor, and then dup() it to use your pipe, and then you can listen to that file descriptor for output. I have actually written std::iostream-derived classes that do exactly this with stdin and stdout, so you can read/write a child process just like an ordinary file.

  9. #9
    Registered User
    Join Date
    Jun 2010
    Posts
    29
    here's my effort. I've redirected stdout of the child to a pipe. The resulting output is on below.I still have some problems..

    1- Can anyone explain why the parent process only reads from the pipe after the child has terminated?

    2- Also, why "Connected PLAYSTATION(R)3 Controller (00:23:06:A4:E6:AA)" isn't sent into the pipe? this message is sent with syslog() instead of printf().


    Code:
     int fd[2];
    
        if( pipe(fd) !=0 )
        {
          perror("Failed to create pipe");
          exit(EXIT_FAILURE);
        }
    
        switch ( fork() )
        {
          case -1:
    	perror("Failed to fork");
    	exit(EXIT_FAILURE);
    	break;
    
          case 0:
    
    	if( dup2(fd[1],STDOUT_FILENO) ==-1 )
    	{
    	  perror("Fail redirecting stdout");
    	  exit(EXIT_FAILURE);
    	}
    	close(fd[0]);
    
    	if(execl("/usr/bin/sixad","sixad","-s",NULL)==-1)
    	  perror("Child unable to execute sixad");
    	exit(EXIT_FAILURE);
    	break;
    
          default:
    	printf("parent\n");
    	close(fd[1]);
    	char buf[500];
    
    	while(1)
    	{
    	  printf("while\n");
    	  if ( read(fd[0], buf, sizeof(buf)) <= 0)
    	  {
    	    perror("Fail reading from pipe:\n ");
    	    exit(EXIT_FAILURE);
    	  }
    
    	  printf("Read from pipe:\n %s",buf);
    	}
        }
    Output:
    parent
    while
    (sixad source code: syslog(LOG_INFO, "Connected PLAYSTATION(R)3 Controller (%s)", bda); )

    Output Continuation:
    sixad[7953]: sixad started, press the PS button now
    sixad[7969]: Connected PLAYSTATION(R)3 Controller (00:23:06:A4:E6:AA)
    (I pressed ctrl+c in the console)

    Output Continuation
    ^C
    sixad[7953]: Exit
    Read from pipe:
    sixad settings:
    Enable LEDs: 1
    js# as LED #: 1
    Start LED #: 1
    LED # increase: 1
    LED animation: 1
    Buttons: 1
    Sens. buttons: 1
    Axis: 1
    Accelerometers: 1
    Acceleration: 0
    Speed: 0
    Position: 0
    Rumble: 0
    Debug: 0
    while
    Fail reading from pipe:
    : Success
    Note: sixad settings are printed with printf
    Last edited by frs; 07-16-2010 at 11:14 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C# Socket Listen On Specific Port
    By pobri19 in forum C# Programming
    Replies: 2
    Last Post: 05-25-2010, 06:01 AM
  2. Not able to create 1024 socket request.
    By rahul.shukla in forum Networking/Device Communication
    Replies: 3
    Last Post: 02-15-2010, 03:49 PM
  3. Minor Problem With Fork And Listen
    By Geolingo in forum Linux Programming
    Replies: 4
    Last Post: 09-19-2003, 08:19 PM
  4. homework!!!! (listen to me people)
    By mitchwardrop in forum C++ Programming
    Replies: 5
    Last Post: 09-26-2001, 02:12 PM