wait()
ビジー待機またはビジースリープループを使用する以外に、システムコールをタイムアウトで使用する方法はありますか?
fork
それ自体とexec
子の実行可能ファイルである親プロセスがあります。次に、子が終了するのを待ち、適切な手段で出力を取得して、さらに処理を実行します。プロセスが一定時間内に終了しない場合は、実行がタイムアウトしたと見なされ、別の処理が実行されます。残念ながら、問題の性質上、このタイムアウト検出は必要です。
wait()
ビジー待機またはビジースリープループを使用する以外に、システムコールをタイムアウトで使用する方法はありますか?
fork
それ自体とexec
子の実行可能ファイルである親プロセスがあります。次に、子が終了するのを待ち、適切な手段で出力を取得して、さらに処理を実行します。プロセスが一定時間内に終了しない場合は、実行がタイムアウトしたと見なされ、別の処理が実行されます。残念ながら、問題の性質上、このタイムアウト検出は必要です。
タイムアウトを取る待機呼び出しはありません。
代わりにできることは、SIGCHLD のフラグを設定するシグナル ハンドラーをインストールし、select() を使用してタイムアウトを実装することです。select() はシグナルによって中断されます。
static volatile int punt;
static void sig_handler(int sig)
{
punt = 1;
}
...
struct timeval timeout = {10,0};
int rc;
signal(SIGCHLD, sig_handler);
fork/exec stuff
//select will get interrupted by a signal
rc = select(0, NULL,NULL,NULL, &timeout );
if (rc == 0) {
// timed out
} else if (punt) {
//child terminated
}
ただし、処理する必要がある他の信号がある場合は、さらにロジックが必要です
オプション、スリープとwaitpid
併用できます。WNOHANG
while(waitpid(pid, &status, WNOHANG) == 0) {
sleep(1);
}
しかし、これはアクティブな睡眠になります。ただし、このwait
タイプの関数を使用する方法は他にありません。
Linux では、 を使用してこの問題を解決することもできますsignalfd
。signalfd
基本的に一連のシグナルを受け取り、読み取り可能な fd を作成します。読み取った各ブロックは、発火したシグナルに対応しています。(これらのシグナルが実際に送信されないように、これらのシグナルを sigprocmask でブロックする必要があります。)
の利点は、 、、またはでsignalfd
fd を使用できることです。これらはすべてタイムアウトを許可し、他のものも待機できるようにします。select
poll
epoll
1 つの注意: 対応する信号struct signalfd_siginfo
が読み取られる前に同じ信号が 2 回発火した場合、1 つの通知しか受信しません。したがって、指示を取得したら、-1 が返されるまで繰り返すSIGCHLD
必要があります。waitpid(-1, &status, &WNOHANG)
FreeBSD では、 との typeを使用kqueue
して、より直接的に同じ効果を得ることができます。(SIGCHLD イベントを kqueue することもできますが、EVFILT_PROC を使用すると、すべての子に対してグローバルにではなく、子 pid でイベントを指定できます。) これは Mac OS X でも動作するはずですが、試したことはありません。kevent
EVFILT_PROC