1

更新: これはタイミングの問題のようです。kill の呼び出しの前に sleep の呼び出しを追加すると、すべてが期待どおりに機能します。

私は clone(2) で遊んでいて、それがどのように機能するかを理解しようとしています。現在、複製されたプロセスにシグナルを送信する際に問題が発生しています。次のコードがあります。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>

volatile int keep_going = 1;

typedef void (*sighandler_t)(int);

void handler(int sig) {
   printf("Signal Received\n");
   keep_going = 0;
}

int thread_main(void* arg) {
   struct sigaction usr_action;
   sigset_t block_mask;
   sigfillset(&block_mask);
   usr_action.sa_handler = &handler;
   usr_action.sa_mask = block_mask;
   usr_action.sa_flags = 0;
   sigaction(SIGUSR1, &usr_action, NULL);
   printf("Hello from cloned thread\n");
   while(keep_going);
}

int main(int argc, char **argv) {
   void* stack = malloc(4096);
   int flags = SIGCHLD;
   int child_tid = clone(&thread_main, stack + 4096, flags, NULL);
   if (child_tid < 0) {
      perror("clone");
      exit(EXIT_FAILURE);
   }
   printf("My pid: %d, child_tid: %d\n", (int) getpid(), (int) child_tid);
   int kill_ret = kill(child_tid, SIGUSR1);
   if (kill_ret < 0) {
      perror("kill");
      exit(EXIT_FAILURE);
   }
   int status = 0;
   pid_t returned_pid = waitpid(child_tid, &status, 0);
   if (returned_pid < 0) {
      perror("waitpid");
      exit(EXIT_FAILURE);
   }
   if (WIFEXITED(status)) {
      printf("exited, status=%d\n", WEXITSTATUS(status));
   } else if (WIFSIGNALED(status)) {
      printf("killed by signal %d\n", WTERMSIG(status));
   } else if (WIFSTOPPED(status)) {
      printf("stopped by signal %d\n", WSTOPSIG(status));
   } else if (WIFCONTINUED(status)) {
      printf("continued\n");
   }
   exit(EXIT_SUCCESS);
}

次の出力が得られます。

My pid: 14101, child_tid: 14102
killed by signal 10

子は明らかにシグナルの結果として殺されましたが、シグナルハンドラが呼び出されなかったのはなぜですか?

4

3 に答える 3

2

競合状態を回避するには、呼び出しの前に親でシグナルをキャッチしclone()ます。子は、親のシグナル ハンドラーのコピーを継承します。必要に応じて、後で親で SIG_DFL にリセットできます。(また、getpid()親で SIG_DFL の動作をエミュレートする場合は、async-signal-safe です)。

于 2011-07-15T20:19:22.423 に答える
0

最初に奇妙なのは、このメッセージが表示されなかったことです。

"Hello from cloned thread\n"

したがって、シグナルハンドラをセットアップする前に、子トレッドが終了します。

編集:睡眠に関するあなたのコメントを見ました。sigactionが実行されるときに設定される別の変数を追加してみてください。この変数が設定されなくなるまで、メイン スレッドをブロックする必要があります。

于 2011-07-15T19:36:15.960 に答える