メッセージをソケットに受信するサーバーがあり、受信したメッセージごとに fork exec を実行します。この部分は正常に動作しているようです。
しかし、これをノンブロッキング モードで行う必要があるため、waitpid()
(フォーラムの多くのトピックで説明されているように) 終了したすべての子プロセスを適切にクリーンアップするハンドラを作成しました。
問題は、このハンドラーが私のpselect
コマンドに対して中断されたシステム コールを生成し、次のメッセージでプログラムを停止することです。
"select(): Interrupted system call"
sigprocmask()
「競合状態の防止」などのフォーラムでこの問題の説明を見つけたので、いくつかのシグナルをブロックするために使用しようとしましたが、うまくいきませんでした。
これは些細な問題だと思いますが、この種のプログラムを使用するのはこれが初めてです。
助けが必要です。前もって感謝します。
プログラムは次のとおりです。
void
clean_up_child_process (int signal_number)
{
pid_t p;
int status;
while (1)
{
p = waitpid (-1, &status, WNOHANG);
if (p == -1)
{
if (errno == EINTR)
{
continue;
}
break;
}
else if (p == 0)
{
break;
}
}
}
static void
app (void)
{
SOCKET sock;
char commande[BUF_SIZE];
char res_cmd[BUF_SIZE];
int max;
int n;
sock = init_connection ();
max = sock;
fd_set rdfs;
sigemptyset (&sigmask);
sigaddset (&sigmask, SIGCHLD);
sigaddset (&sigmask, SIGINT);
sigaddset (&sigmask, SIGTSTP);
sigaddset (&sigmask, SIGTERM);
sigprocmask (SIG_BLOCK, &sigmask, NULL);
struct sigaction sigchld_action;
memset (&sigchld_action, 0, sizeof (sigchld_action));
sigchld_action.sa_handler = &clean_up_child_process;
sigaction (SIGCHLD, &sigchld_action, NULL);
while (1)
{
int i = 0;
FD_ZERO (&rdfs);
/* add STDIN_FILENO */
FD_SET (STDIN_FILENO, &rdfs);
/* add the connection socket */
FD_SET (sock, &rdfs);
sigemptyset (&empty_mask);
if (pselect (max + 1, &rdfs, NULL, NULL, NULL, &empty_mask) == -1)
if (errno != EINTR)
{
perror ("select()");
exit (errno);
}
if (FD_ISSET (STDIN_FILENO, &rdfs))
{
/* stop process when type on keyboard */
// break; must be disable to avoid bad exits
}
else if (FD_ISSET (sock, &rdfs))
{
/* new client */
SOCKADDR_IN csin = { 0 };
size_t sinsize = sizeof csin;
int csock = accept (sock, (SOCKADDR *) & csin, &sinsize);
if (csock == SOCKET_ERROR)
{
perror ("accept()");
continue;
}
if ((n = recv (csock, commande, BUF_SIZE - 1, 0)) < 0)
{
perror ("recv(commande)");
n = 0;
continue;
}
commande[n] = 0;
if ((n = fork ()) == -1)
perror ("fork()");
else if (n == 0)
{
close (STDOUT_FILENO);
dup (csock);
close (STDERR_FILENO);
dup (csock);
execlp (commande, commande, 0);
}
else
{
closesocket (csock);
}
}
}
end_connection (sock);
}