waitpid.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * waitpid.c --
  3.  *
  4.  * This procedure emulates the POSIX waitpid kernel call on
  5.  * BSD systems that don't have waitpid but do have wait3.
  6.  * This code is based on a prototype version written by
  7.  * Mark Diekhans and Karl Lehenbauer.
  8.  *
  9.  * Copyright (c) 1993 The Regents of the University of California.
  10.  * Copyright (c) 1994 Sun Microsystems, Inc.
  11.  *
  12.  * See the file "license.terms" for information on usage and redistribution
  13.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  *
  15.  * RCS: @(#) $Id: waitpid.c,v 1.3 2000/01/11 22:08:50 hobbs Exp $
  16.  */
  17. #include "tclInt.h"
  18. #include "tclPort.h"
  19. #ifndef pid_t
  20. #define pid_t int
  21. #endif
  22. /*
  23.  * A linked list of the following structures is used to keep track
  24.  * of processes for which we received notification from the kernel,
  25.  * but the application hasn't waited for them yet (this can happen
  26.  * because wait may not return the process we really want).  We
  27.  * save the information here until the application finally does
  28.  * wait for the process.
  29.  */
  30. typedef struct WaitInfo {
  31.     pid_t pid; /* Pid of process that exited. */
  32.     WAIT_STATUS_TYPE status; /* Status returned when child exited
  33.  * or suspended. */
  34.     struct WaitInfo *nextPtr; /* Next in list of exited processes. */
  35. } WaitInfo;
  36. static WaitInfo *deadList = NULL; /* First in list of all dead
  37.  * processes. */
  38. /*
  39.  *----------------------------------------------------------------------
  40.  *
  41.  * waitpid --
  42.  *
  43.  * This procedure emulates the functionality of the POSIX
  44.  * waitpid kernel call, using the BSD wait3 kernel call.
  45.  * Note:  it doesn't emulate absolutely all of the waitpid
  46.  * functionality, in that it doesn't support pid's of 0
  47.  * or < -1.
  48.  *
  49.  * Results:
  50.  * -1 is returned if there is an error in the wait kernel call.
  51.  * Otherwise the pid of an exited or suspended process is
  52.  * returned and *statusPtr is set to the status value of the
  53.  * process.
  54.  *
  55.  * Side effects:
  56.  * None.
  57.  *
  58.  *----------------------------------------------------------------------
  59.  */
  60. #ifdef waitpid
  61. #   undef waitpid
  62. #endif
  63. pid_t
  64. waitpid(pid, statusPtr, options)
  65.     pid_t pid; /* The pid to wait on.  Must be -1 or
  66.  * greater than zero. */
  67.     int *statusPtr; /* Where to store wait status for the
  68.  * process. */
  69.     int options; /* OR'ed combination of WNOHANG and
  70.  * WUNTRACED. */
  71. {
  72.     register WaitInfo *waitPtr, *prevPtr;
  73.     pid_t result;
  74.     WAIT_STATUS_TYPE status;
  75.     if ((pid < -1) || (pid == 0)) {
  76. errno = EINVAL;
  77. return -1;
  78.     }
  79.     /*
  80.      * See if there's a suitable process that has already stopped or
  81.      * exited. If so, remove it from the list of exited processes and
  82.      * return its information.
  83.      */
  84.     for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
  85.     prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) {
  86. if ((pid != waitPtr->pid) && (pid != -1)) {
  87.     continue;
  88. }
  89. if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) {
  90.     continue;
  91. }
  92. result = waitPtr->pid;
  93. *statusPtr = *((int *) &waitPtr->status);
  94. if (prevPtr == NULL) {
  95.     deadList = waitPtr->nextPtr;
  96. } else {
  97.     prevPtr->nextPtr = waitPtr->nextPtr;
  98. }
  99. ckfree((char *) waitPtr);
  100. return result;
  101.     }
  102.     /*
  103.      * Wait for any process to stop or exit.  If it's an acceptable one
  104.      * then return it to the caller;  otherwise store information about it
  105.      * in the list of exited processes and try again.  On systems that
  106.      * have only wait but not wait3, there are several situations we can't
  107.      * handle, but we do the best we can (e.g. can still handle some
  108.      * combinations of options by invoking wait instead of wait3).
  109.      */
  110.     while (1) {
  111. #if NO_WAIT3
  112. if (options & WNOHANG) {
  113.     return 0;
  114. }
  115. if (options != 0) {
  116.     errno = EINVAL;
  117.     return -1;
  118. }
  119. result = wait(&status);
  120. #else
  121. result = wait3(&status, options, 0);
  122. #endif
  123. if ((result == -1) && (errno == EINTR)) {
  124.     continue;
  125. }
  126. if (result <= 0) {
  127.     return result;
  128. }
  129. if ((pid != result) && (pid != -1)) {
  130.     goto saveInfo;
  131. }
  132. if (!(options & WUNTRACED) && (WIFSTOPPED(status))) {
  133.     goto saveInfo;
  134. }
  135. *statusPtr = *((int *) &status);
  136. return result;
  137. /*
  138.  * Can't return this info to caller.  Save it in the list of
  139.  * stopped or exited processes.  Tricky point: first check for
  140.  * an existing entry for the process and overwrite it if it
  141.  * exists (e.g. a previously stopped process might now be dead).
  142.  */
  143. saveInfo:
  144. for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
  145.     if (waitPtr->pid == result) {
  146. waitPtr->status = status;
  147. goto waitAgain;
  148.     }
  149. }
  150. waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo));
  151. waitPtr->pid = result;
  152. waitPtr->status = status;
  153. waitPtr->nextPtr = deadList;
  154. deadList = waitPtr;
  155. waitAgain: continue;
  156.     }
  157. }