ここに紹介した意図は、このテクニックの紹介である。
実はシグナルを受けるサーバー側で recvmsg
で待機するジョブにシグナルを
受けるときは少々工夫が必要となる。
HTTP サーバーを初めとするサーバーが recvmsg
によって待機しているときに
シグナルを受けると、
そのシグナルに関連づけられたシグナル・ハンドラーとしての関数が
定義されていれば、その関数が実行される。
recvmsg
は再び待機状態になるのではなく
EINTR : Interrupted function call.
のエラー・メッセージで終了してしまう。
この EINTR
というエラーは Linux では
「 データが受信可能になる前に受信がシグナルによって割り込まれました。 」
というエラーである。
という状態となる。
この 2. の EINTR
というエラーが問題でこれは recvmsg
でデータを待機していたのだが
シグナルによる割り込みのために受信が中断された、という意味である。
このエラーを回避しないと recvmsg
による待機ジョブは終了してしまうことになる。
シグナル待機をもう一度、再セットしてから処理を継続する。
0021.00 #include <errno.h> : 0153.00 struct sigaction sigact; : 0395.00 rc = recvmsg(worker_sd, &msg, 0); 0396.00 if(rc < 0){/* recvmsg エラー */ 0397.00 if(errno == EINTR){/* シグナル割り込み */ 0398.00 setSignal(); 0399.00 continue; 0400.00 }/* シグナル割り込み */ : 1672.00 /********************/ 1673.00 void setSignal(void) 1674.00 /********************/ 1675.00 { 1676.00 /* recvmsg のための初期化 */ 1677.00 memset(&msg, 0, sizeof(msg)); 1678.00 memset(iov, 0, sizeof(iov)); 1679.00 iov[0].iov_base = buffer; 1680.00 iov[0].iov_len = sizeof(buffer); 1681.00 msg.msg_iov = iov; 1682.00 msg.msg_iovlen = 1; 1683.00 msg.msg_accrights = (char*)&sockfd; 1684.00 msg.msg_accrightslen = sizeof(sockfd); 1685.00 1686.00 sigemptyset(&sigact.sa_mask); 1687.00 sigact.sa_flags = 0; 1688.00 sigact.sa_handler = catcher; 1689.00 sigaction(SIGUSR1, &sigact, NULL); 1690.00 sigaction(SIGUSR2, &sigact, NULL); 1691.00 sigaction(SIGUSR3, &sigact, NULL); 1692.00 }
recvmsg
のエラーが EINTR
( EINTR
は errno.h
の中で定義されている ) であれば
もう一度 setSignal
関数によって シグナル構造体 sigact
を再セットしてから
continue
で処理を継続する。
このとき recvmsg
の初期化も同時に行なっているので次の recvmsg
も正しく待機させることができる。
このテクニックは Webサイトを探してもどこにもまだ紹介されていない実用的なテクニックである。
これによって Spoolライターの サーバーでの子ブロセスの QTEMP
情報を自由に検索することが
できるようになったのである。