Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       wait, waitpid, waitid - プロセスの状態変化を待つ

書式

       #include <sys/types.h>
       #include <sys/wait.h>

       pid_t wait(int *wstatus);

       pid_t waitpid(pid_t pid, int *wstatus, int options);

       int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
                       /* これは glibc と POSIX のインターフェイスである。
                          生のシステムコールについての情報は「注意」の節を参照。 */

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):

       waitid():
           glibc 2.26 以降: _XOPEN_SOURCE >= 500 ||
               _POSIX_C_SOURCE >= 200809L
           glibc 2.25 以前:
               _XOPEN_SOURCE
                   || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
                   || /* Glibc versions <= 2.19: */ _BSD_SOURCE

説明

       これらのシステムコールはいずれも、呼び出し元プロセスの子プロセスの 状態変化を待ち、状態が変化したその子プ
       ロセスの情報を取得するのに 使用される。 状態変化とは以下のいずれかである:  子プロセスの終了、シグナルによ
       る子プロセスの停止、 シグナルによる子プロセスの再開。 子プロセスが終了した場合は、wait を実行することで、
       システムがその子プロセスに関連するリソースを解放できるようになる。 wait  が実行されなかった場合には、終了
       した子プロセスは 「ゾンビ」状態で残り続ける (下記の注意の章を参照のこと)。

       子プロセスの状態変化がすでに発生していた場合、これらのコールは すぐに復帰する。それ以外の場合は、子プロセ
       スの状態変化が起こるか、 シグナルハンドラーによりシステムコールが中断されるまで、 停止 (block) する (後者
       は、  sigaction(2)  の SA_RESTART フラグによりシステムコールが自動的に再スタートするようになっていない 場
       合の動作である)。 以下の説明では、状態変化が起こったがこれらのシステムコールのいずれかに よって待たれてい
       ない子プロセスを waitable (待ち可能) と呼ぶ。

   wait()  waitpid()
       wait()   システムコールは、子プロセスのいずれかが終了するまで  呼び出し元のスレッドの実行を一時停止する。
       呼び出し wait(&wstatus) は以下と等価である:

           waitpid(-1, &wstatus, 0);

       waitpid() システムコールは、 pid 引数で指定した子プロセスの状態変化が起こるまで、  呼び出し元のスレッドの
       実行を一時停止する。デフォルトでは、  waitpid() は子プロセスの終了だけを待つが、この動作は options 引数に
       より変更可能である。

       pid に指定できる値は以下の通り:

       < -1   プロセスグループID が pid の絶対値に等しい子プロセスのいずれかが終了するまでを待つ。

       -1     子プロセスのどれかが終了するまで待つ。

       0      プロセスグループ ID が、waitpid() が呼ばれた時点での呼び出し元のプロセスのプロセスグループ ID と等
              しい子プロセスを待つ。

       > 0    プロセスID が pid に等しい子プロセスを待つ。

       options の値は次の定数の 0 個以上の論理和である:

       WNOHANG
              状態変化が起こった子プロセスがない場合にすぐに復帰する。

       WUNTRACED
              子プロセスが停止した場合にも復帰する (子プロセスが ptrace(2)  でトレースされている場合は除く)。 こ
              のオプションが指定されていない場合でも、停止したプロセスが 「トレース (traced)」されていれば、子プ
              ロセスの状態が報告される。

       WCONTINUED (Linux 2.6.10 以降)
              停止した子プロセスが SIGCONT の配送により再開した場合にも復帰する。

       (Linux 専用オプションについては後述する)

       wstatus が NULL でなければ、 wait()  や waitpid()  は status で指す int に状態情報を格納する。 この整数は
       以下のマクロを使って検査できる。 (これらのマクロの引数には、 wait()  や waitpid()  が書き込んだ整数そのも
       のを指定する。ポインターではない!)

       WIFEXITED(wstatus)
              子プロセスが正常に終了した場合に真を返す。 「正常に」とは、 exit(3)  か _exit(2)  が呼び出された場
              合、もしくは main() から復帰した場合である。

       WEXITSTATUS(wstatus)
              子プロセスの終了ステータスを返す。 終了ステータスは  status  引数の下位  8ビットで構成されており、
              exit(3)   や _exit(2)  の呼び出し時に渡された値、もしくは main() の return 文の 引数として指定され
              た値である。 このマクロを使用するのは WIFEXITED が真を返した場合だけにすべきである。

       WIFSIGNALED(wstatus)
              子プロセスがシグナルにより終了した場合に真を返す。

       WTERMSIG(wstatus)
              子プロセス終了の原因となったシグナルの番号を返す。 このマクロを使用するのは WIFSIGNALED が真を返し
              た場合だけにすべきである。

       WCOREDUMP(wstatus)
              returns  true if the child produced a core dump (see core(5)).  This macro should be employed only
              if WIFSIGNALED returned true.

              This macro is not specified in POSIX.1-2001 and is not  available  on  some  UNIX  implementations
              (e.g., AIX, SunOS).  Therefore, enclose its use inside #ifdef WCOREDUMP ... #endif.

       WIFSTOPPED(wstatus)
              子プロセスがシグナルの配送により停止した場合に真を返す。      これが真になるのは、システムコールが
              WUNTRACED を指定して呼び出された場合か、子プロセスがトレースされている場合 (ptrace(2)  参照)  だけ
              である。

       WSTOPSIG(wstatus)
              子プロセスを停止させたシグナルの番号を返す。 このマクロを使用するのは WIFSTOPPED が 0 以外を返した
              場合だけにすべきである。

       WIFCONTINUED(wstatus)
              (Linux 2.6.10 以降)  子プロセスが SIGCONT の配送により再開した場合に真を返す。

   waitid()
       waitid()  システムコール (Linux 2.6.9 以降で利用可能) を使うと、 子プロセスのどの状態変化を待つかについて
       より細かな制御ができる。

       引数 idtypeid でどの子プロセスを待つかを選択する:

       idtype == P_PID
              プロセスID が id と一致する子プロセスを待つ。

       idtype == P_PIDFD (since Linux 5.4)
              Wait  for  the  child  referred to by the PID file descriptor specified in id.  (See pidfd_open(2)
              for further information on PID file descriptors.)

       idtype == P_PGID
              Wait for any child whose process group ID matches id.  Since Linux 5.4, if id is zero,  then  wait
              for  any  child that is in the same process group as the caller's process group at the time of the
              call.

       idtype == P_ALL
              子プロセス全部を対象に待つ。 id は無視される。

       子プロセスのどの状態変化を待つかは以下のフラグで指定する (options には  1個以上のフラグの論理和をとって指
       定する):

       WEXITED
              子プロセスの終了を待つ。

       WSTOPPED
              子プロセスがシグナルの配送により停止するのを待つ。

       WCONTINUED
              (停止していた) 子プロセスが SIGCONT が配送されて再開するのを待つ。

       さらに以下のフラグを論理和の形で options に指定できる:

       WNOHANG
              waitpid()  と同様。

       WNOWAIT
              waitable 状態のプロセスをそのままにする。この後で wait コールを 使って、同じ子プロセスの状態情報を
              もう一度取得することができる。

       成功した場合には、 waitid()  は infop が指す siginfo_t 構造体の以下のフィールドを設定する:

       si_pid 子プロセスのプロセスID。

       si_uid 子プロセスの実ユーザーID (このフィールドは他のほとんどの実装では設定されない)。

       si_signo
              常に SIGCHLD が設定される。

       si_status
              _exit(2)   (か  exit(3))   に指定された子プロセスの終了ステータス、もしくは   子プロセスの終了、停
              止、再開の原因となったシグナルが設定される。 このフィールドをどう解釈するかは、 si_code フィールド
              を参照して決めることができる。

       si_code
              以下のいずれかが設定される: CLD_EXITED (子プロセスが _exit(2)  を呼び出した); CLD_KILLED (シグナル
              により子プロセスが  kill された); CLD_DUMPED (シグナルにより子プロセスが kill され、コアダンプが行
              われた); CLD_STOPPED (シグナルにより子プロセスが停止した); CLD_TRAPPED (トレースされていた子プロセ
              スがトラップを受信した); CLD_CONTINUED (SIGCONT により子プロセスが再開された)。

       If  WNOHANG  was  specified  in  options  and  there  were no children in a waitable state, then waitid()
       returns 0 immediately and the state of the siginfo_t  structure  pointed  to  by  infop  depends  on  the
       implementation.   To  (portably)  distinguish  this case from that where a child was in a waitable state,
       zero out the si_pid field before the call and check for a nonzero value in  this  field  after  the  call
       returns.

       POSIX.1-2008  Technical  Corrigendum  1  (2013)  adds  the  requirement that when WNOHANG is specified in
       options and there were no children in a waitable state, then waitid()  should zero  out  the  si_pid  and
       si_signo fields of the structure.  On Linux and other implementations that adhere to this requirement, it
       is not necessary to zero out the si_pid field before calling waitid().  However, not all  implementations
       follow the POSIX.1 specification on this point.

返り値

       wait(): 成功すると、終了した子プロセスのプロセスID を返す。 エラーの場合 -1 を返す。

       waitpid():  成功すると、状態が変化した子プロセスのプロセスID を返す。 WNOHANG が指定されていて、 pid で指
       示された子プロセスが一つ以上存在するが、どの子プロセスでも  状態変化が起こっていなかった場合は、  0  を返
       す。 エラーの場合 -1 を返す。

       waitid(): 成功すると 0 を返す。 WNOHANG が指定されていて、 pid で指示された子プロセスで状態変化が起こって
       いなかった場合にも 0 を返す。

       エラーの場合 -1 を返す。 エラーの場合、これらのシステムコールはいずれも errno に適切な値を設定する。

エラー

       ECHILD (wait()  の場合)  呼び出し元プロセスには、wait を行っていない子プロセスはない。

       ECHILD (waitpid()  か waitid()  の場合)  pid (waitpid())  か idtypeid (waitid())   で指定したプロセス
              が存在しないか、呼び出し元プロセスの子プロセスでない  (SIGCHLD  の動作に  SIG_IGN を設定した場合に
              は、自分自身の子プロセスでも起こりうる。 スレッドに関しては「Linux での注意」の節も参照すること)。

       EINTR  WNOHANG が設定されておらず、禁止 (block) されていないシグナルや SIGCHLD を受信した。 signal(7)  参
              照。

       EINVAL options 引数が不正である。

準拠

       SVr4, 4.3BSD, POSIX.1-2001.

注意

       A  child that terminates, but has not been waited for becomes a "zombie".  The kernel maintains a minimal
       set of information about the zombie process (PID, termination status,  resource  usage  information)   in
       order  to  allow  the parent to later perform a wait to obtain information about the child.  As long as a
       zombie is not removed from the system via a wait, it will consume a slot in the kernel process table, and
       if  this  table  fills,  it  will  not  be  possible  to  create  further processes.  If a parent process
       terminates, then its "zombie" children (if any)  are adopted by init(1), (or by the  nearest  "subreaper"
       process   as  defined  through  the  use  of  the  prctl(2)  PR_SET_CHILD_SUBREAPER  operation);  init(1)
       automatically performs a wait to remove the zombies.

       POSIX.1-2001 では以下のように規定されている。 SIGCHLD の動作が SIG_IGN に設定されたか、 SIGCHLD  に対して
       SA_NOCLDWAIT  フラグが設定された場合  (sigaction(2)  参照)、終了した子プロセスはゾンビにはならず、 wait()
       や  waitpid()   の呼び出しは全ての子プロセスが終了するまで停止し、  子プロセスが全部終了した後  errnoECHILD  を設定して失敗する。 (もともとの POSIX 標準は SIGCHLDSIG_IGN を設定した場合の振る舞いを未規定
       のままにしている。  SIGCHLD   のデフォルトの動作が「無視」であるにもかかわらず、   SIGCHLD   の動作として
       SIG_IGN を明示的に設定した場合にはゾンビプロセスの子プロセスの扱いが 異なる点に注意すること。)

       Linux  2.6  はこの仕様に準拠している。 しかし、Linux 2.4 (とそれ以前のバージョン) はそうではない: SIGCHLD
       が無視される状態で wait()  または waitpid()  が呼び出された場合、 SIGCHLD  が無視されていないかのように振
       る舞う。 つまり、呼び出しによって次の子プロセスの終了までブロックされ、 終了した子プロセスの PID と状態が
       返される。

   Linux での注意
       Linux カーネルでは、カーネルによってスケジュールされるスレッドは プロセスと明確に区別できる構成要素ではな
       い。スレッドは Linux 固有の clone(2)  システムコールを使用して生成されるプロセスに過ぎない。 移植性のある
       pthread_create(3) コールのような他のルーチンは clone(2)   を使用して実装されている;  これらでは  waitid()
       を使うことはできない。  Linux 2.4 より前では、スレッドは単に特殊なプロセスであったので、 例え同じスレッド
       グループであっても、  あるスレッドが別のスレッドの子プロセスが終了するのを待つことは出来なかった。   しか
       し、POSIX ではこのような機能を規定しており、 Linux 2.4 以降では、あるスレッドが同じスレッドグループの他の
       スレッドの 子プロセスが終了するのを待つことができるようになった。  そして将来はこれがデフォルトの動作にな
       るであろう。

       The  following  Linux-specific  options  are for use with children created using clone(2); they can also,
       since Linux 4.7, be used with waitid():

       __WCLONE
              "clone" な子プロセスだけを待つ。 指定されなかった場合は非 "clone" な子プロセスだけを待つ  ("clone"
              な子プロセスは、終了時に親プロセスへ全くシグナルを送らないか、  SIGCHLD 以外のシグナルを送る)。 こ
              のオプションは __WALL も指定された場合は無視される。

       __WALL (Linux 2.4 以降)
              "clone" であるかないかに関わらず、 全ての子プロセスを待つ。

       __WNOTHREAD (Linux 2.4 以降)
              同じスレッドグループの他のスレッドの子プロセスは待たない。  Linux  2.4  より前ではデフォルトであっ
              た。

       Since Linux 4.7, the __WALL flag is automatically implied if the child is being ptraced.

   C ライブラリとカーネルの違い
       wait()  is actually a library function that (in glibc) is implemented as a call to wait4(2).

       On some architectures, there is no waitpid()  system call; instead, this interface is implemented via a C
       library wrapper function that calls wait4(2).

       生の waitid() システムコールは struct rusage * 型の第 5 引数を取る。 この引数が NULL 以外の場合、  この引
       数が子プロセスのリソース使用状況を返すのに使用される。    これは   wait4(2)   と同じ方法である。   詳細は
       getrusage(2) を参照。

バグ

       POSIX.1-2008 によると、 waitid() を呼び出すアプリケーションは、 infopsiginfo_t 構造体を指していること
       (つまり  infop  が NULL でないポインターであること) を保証しなければならない。 Linux では、 infop が NULL
       の場合、 waitid() は成功し、wait している子プロセスのプロセス  ID  を返す。  アプリケーションは、この食い
       違った、非標準で、不必要な機能に依存しないようにすべきである。

       以下のプログラムは、 fork(2)  と waitpid()  の使用方法の例を示している。 このプログラムでは子プロセスを生
       成する。 コマンドライン引数が指定されなかったときは、 子プロセスは  pause(2)   を使ってその実行を一時停止
       し、ユーザーがその子プロセスに シグナルを送信できるようにする。 コマンドライン引数が指定された場合は、 子
       プロセスは直ちに終了し、  コマンドラインで指定された整数を終了ステータスとして使用する。   親プロセスは、
       waitpid()   を使って子プロセスを監視し、  wait  のステータス値を上記の  W*() マクロを使って解析するという
       ループを実行する。

       以下のシェルのセッションはこのプログラムの使用例を示したものである。

           $ ./a.out &
           Child PID is 32360
           [1] 32359
           $ kill -STOP 32360
           stopped by signal 19
           $ kill -CONT 32360
           continued
           $ kill -TERM 32360
           killed by signal 15
           [1]+  Done                    ./a.out
           $

   プログラムのソース

       #include <sys/wait.h>
       #include <stdint.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <stdio.h>

       int
       main(int argc, char *argv[])
       {
           pid_t cpid, w;
           int wstatus;

           cpid = fork();
           if (cpid == -1) {
               perror("fork");
               exit(EXIT_FAILURE);
           }

           if (cpid == 0) {            /* Code executed by child */
               printf("Child PID is %jd\n", (intmax_t) getpid());
               if (argc == 1)
                   pause();                    /* Wait for signals */
               _exit(atoi(argv[1]));

           } else {                    /* Code executed by parent */
               do {
                   w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
                   if (w == -1) {
                       perror("waitpid");
                       exit(EXIT_FAILURE);
                   }

                   if (WIFEXITED(wstatus)) {
                       printf("exited, status=%d\n", WEXITSTATUS(wstatus));
                   } else if (WIFSIGNALED(wstatus)) {
                       printf("killed by signal %d\n", WTERMSIG(wstatus));
                   } else if (WIFSTOPPED(wstatus)) {
                       printf("stopped by signal %d\n", WSTOPSIG(wstatus));
                   } else if (WIFCONTINUED(wstatus)) {
                       printf("continued\n");
                   }
               } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
               exit(EXIT_SUCCESS);
           }
       }

関連項目

       _exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2),  signal(2),  wait4(2),  pthread_create(3),
       core(5), credentials(7), signal(7)

この文書について

       この  man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告
       に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。