/>
wait( )
 jbwyatt.com

.. terms and concepts

    
 shell:  
   ptree pid            -> shows process tree (children)
   ps                   -> shows current process info
   ps -ef | grep wyatt  -> shows all processes of wyatt  

ORPHAN (parent dead) ====== An orphan process is a computer process whose parent process has finished or terminated. Any orphaned process will be immediately adopted by the special init system process (PID = 1). This occurs automatically. The orphaned process now has the "init" process as its parent. ZOMBIE (dead but undead) ====== A zombie process is a process that has completed execution but still has an entry in the process table (PCB). This entry is still needed to allow the process that started the zombie process to read the child's exit status.
wait, waitpid - wait for process termination ============================================ Parent spawns child process. Parent process may then issue a wait() call, which suspends execution of the parent process while the child executes. When the child terminates, it returns an exit status to the operating system, which is then returned to the waiting parent. Parent resumes execution. If a parent issues a wait and there are no children, the wait() returns immediately.
The wait() system call suspends execution of the current process until one of its children terminates. The call wait(&status) is equivalent to: waitpid(-1, &status, 0); The waitpid() system call suspends execution of the current process until a child specified by pid argument has changed state. By default, waitpid() waits only for terminated children, but this behaviour is modifiable via the options argument, as described below.
#include <sys/types.h> #include <sys/wait.h> pid_t wait ( int *status ); pid_t waitpid ( pid_t pid, int *status, int options );
RETURN VALUE The process ID of the child which exited, or zero if WNOHANG was used and no child was available, or -1 on error (in which case errno is set).

.. wait()

 
wait()
======
The wait function suspends execution of the current process until a child 
has exited, or until a signal is delivered whose action is to terminate 
the current process or to call a signal handling function. 

If a child has already exited by the time of the call (a "zombie" process), 
the function returns immediately. Any resources used by the child are freed. 

fork and wait (parent and child) ================================
fork and wait (parent and child) ================================ What are possible outputs if parent = 3426 & child = 3427 #include <stdio.h> // parentwaitpid.c #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main (void) { pid_t childpid; // create child childpid = fork(); if (childpid == -1) { // fork error perror("Failed to fork"); return 1; } // CHILD **** // child simply prints and ends if (childpid == 0) fprintf(stderr, "I am child %ld\n", (long)getpid()); // child then exits via return 0 // PARENT waits and ... **** else if (wait(NULL) != childpid) // ... gets interrupted by something other than the child... fprintf(stderr, "An unexpected signal has interrupted the wait!\n"); // ... gets signaled by the child teminating else fprintf(stderr, "I am parent %ld with child %ld\n", (long)getpid(), (long)childpid); // CHILD and PARENT BOTH END HERE return 0; } I am child 3427 I am parent 3426 with child 3427

.. waitpid()

 
waitpid()
=========
The waitpid function suspends execution of the current process until a 
child as specified by the pid argument has exited, or until a signal is 
delivered whose action is to terminate the current process or to call a 
signal handling function. 

If a child as requested by pid has already exited by the time of the 
call (a "zombie" process), the function returns immediately. 
Any system resources used by the child are freed. 

The value of pid can be one of: -1 : wait for any child process; (same as wait ) > 0 : wait for the child whose process ID is equal to the value of pid.
The value of options is an OR of zero or more of the following constants: WNOHANG which means return immediately if no child has exited. WUNTRACED which means return for children which are stopped, and whose status has not been reported.
If status not NULL, wait/waitpid store status info in location pointed to by status Status can be evaluated with the following macros (macros take the stat buffer(an int) as an arg - not a pointer to the buffer!) WIFEXITED(status) is non-zero if the child exited normally. WEXITSTATUS(status) evaluates to the least significant eight bits of the return code of the child which terminated, which may have been set as the argument to a call to exit() or as the argument for a return statement in the main program. This macro can only be evaluated if WIFEXITED returned non-zero. WIFSIGNALED(status) returns true if the child exited because of a signal which was not caught. WTERMSIG(status) returns the number of the signal that caused the child process to terminate. This macro can only be evaluated if WIFSIGNALED returned non-zero. WIFSTOPPED(status) returns true if child process which caused the return is currently stopped; this is only possible if the call was done using WUNTRACED. WSTOPSIG(status) returns the number of the signal which caused the child to stop. This macro can only be evaluated if WIFSTOPPED returned non-zero.

.. predictions?

 
// fanwait.c - fork and wait for kids
// CC fanwait.c
//
// a.out 2
// a.out 4
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

int main(int argc, char *argv[])
{
   pid_t childpid; // return pid from fork
   int i, n, j;

   // check arg number and get arg
   if (argc != 2)
   {
      // fprintf(stderr, "Usage: %s n\n", argv[0]);
      cerr << "Usage is " << argv[0] << " n (20 max num procs)\n";
      return 1;
   }
   n = atoi(argv[1]); // convert ascii to integer

   // spawn n-1 kids
   for (i = 1; i < n; i++)
   {
      // spawn proc and IF CHILD, break; parent stays in loop
      if ((childpid = fork()) == 0)
         break;
   }
   
   // kids here
   if (childpid == 0)
      for (j=0; j<100; j++)
         cout << i-1 <<':'<< j <<' '; // print their index
         
   //parent: when kids are all done WAIT STATUS WILL BE ZERO
   else 
      while(wait(NULL) > 0)   // wait for each child  (does NOT get kid's pid)
         cout << "PARENT\n";  // print and keep waiting until no more kids

   // everyone goes here and prints
   fprintf(stderr, "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
           i, (long)getpid(), (long)getppid(), childpid);
   return 0;
}

could we make it so we fan and make sure kids don't interrupt each other? YES


#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main (int argc, char *argv[]) { pid_t childpid; int i, n, stat, *pstat; pid_t waitreturn; if (argc != 2){ /* check number of command-line arguments */ fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } n = atoi(argv[1]); pstat=&stat; for (i=1; i<n; i++) { if (childpid = fork()) // parent breaks, kid becomes parent break; } while(waitreturn = wait(NULL)) { if ((waitreturn == -1) && (errno != EINTR)) { break; } } fprintf(stderr, "I am process %ld, my parent is %ld\n", (long)getpid(), (long)getppid()); return 0; } jupiter|/export/home/wyatt/private/355$ cc chainwait.c jupiter|/export/home/wyatt/private/355$ a.out 5 I am process 2564, my parent is 2563 I am process 2563, my parent is 2562 I am process 2562, my parent is 2561 I am process 2561, my parent is 2560 I am process 2560, my parent is 29272