在克隆线程上发送和处理信号

时间:2011-07-15 19:24:02

标签: c signals signal-handling

更新:这似乎是一个时间问题。在调用kill之前添加一个sleep进行调用会使一切按预期工作。

我一直在玩克隆(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

由于信号,孩子显然被杀了,为什么信号处理程序没有被调用?

3 个答案:

答案 0 :(得分:2)

为了避免竞争条件,请在clone()电话之前捕捉父母的信号。孩子继承了父母的信号处理程序的副本。如果需要,您可以稍后在父级上将其重置为SIG_DFL。 (另外,getpid()是异步信号安全的,如果你想模仿父级的SIG_DFL行为。)

答案 1 :(得分:1)

孩子没有收到信号,因为在孩子接到sigaction的电话之前,父母正在发送信号,这就是为什么它会被杀死。您应该避免以这种方式设置信号处理程序。仍然如果你想这样做只是确保父等待孩子设置信号处理程序。在这种情况下,您应该看到预期的结果。

答案 2 :(得分:0)

首先,奇怪的是你没有收到这条消息:

"Hello from cloned thread\n"

因此,在设法设置信号处理程序之前,您的孩子会被终止。

编辑: 我刚看到你对睡眠的评论。尝试添加另一个变量,该变量在执行sigaction时设置。应该阻塞主线程,直到没有设置此变量。

相关问题