Отправка и обработка сигнала на клонированном потоке - PullRequest
1 голос
/ 15 июля 2011

ОБНОВЛЕНИЕ: это, кажется, проблема синхронизации.Добавление вызова в спящий режим перед вызовом в kill приводит к тому, что все работает как положено.

Я играл с 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

Ребенок был явно убит в результате сигнала, почему обработчик сигнала не был вызван

Ответы [ 3 ]

2 голосов
/ 16 июля 2011

Чтобы избежать состояния гонки, поймайте сигнал на родителе перед вызовом clone().Ребенок наследует копию обработчиков сигналов родителя.Вы можете сбросить его позже на родительском SIG_DFL, если хотите.(Кроме того, getpid() безопасен для асинхронных сигналов, если вы хотите эмулировать поведение SIG_DFL на родительском элементе).

1 голос
/ 26 апреля 2013

Ребенок не получает сигнал, потому что до того, как ребенок дозвонится до sigaction, родитель отправляет сигнал, и поэтому его убивают. Вы должны избегать установки обработчика сигнала таким образом. Тем не менее, если вы хотите сделать это только так, убедитесь, что родитель ожидает, пока дочерний процесс не установит обработчик сигнала. При таком сценарии вы должны увидеть ожидаемый результат.

0 голосов
/ 15 июля 2011

Первое, что странно, вы не получили это сообщение:

"Hello from cloned thread\n"

поэтому ваш дочерний шаг прекращается до того, как ему удается настроить обработчик сигнала.

EDIT: Я только что видел ваш комментарий о сне. Попробуйте добавить другую переменную, которая устанавливается, когда выполняется sigaction. Основной поток должен быть заблокирован до тех пор, пока эта переменная не будет установлена.

...