2015-03-18 2 views
1

Я пытаюсь написать программу C, которая имеет некоторое количество процессов. Один из них отправляет случайный сигнал в диапазоне SIGRTMIN и SIGRTMAX ко всем другим процессам, но я хочу, чтобы этот сигнал был проигнорирован в основном процессе. Я использовал глобальную переменную, чтобы случайный сигнал игнорировался с помощью SIG_IGN. Похоже, это не помогает, потому что основные остановки с сигналом в реальном времени, когда он хочет игнорировать первый рандомизированный сигнал.связь процесса с сигналами

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <time.h> 

volatile sig_atomic_t disarming_signal = 0; 

void disarming_handler (int sig) { 
    disarming_signal = sig; 
    fprintf(stderr,"signal %d is handeled", disarming_signal); 
} 
int rand_range(int min_n, int max_n){ 
    int rand_n = rand() % (max_n - min_n) + min_n; 
    return rand_n; 
} 
int sethandler (void (*f)(int), int sigNo) { 
    struct sigaction act; 
memset(&act, 0, sizeof(struct sigaction)); 
act.sa_handler = f; 
    if (-1==sigaction(sigNo, &act, NULL)) 
     return -1; 
return 0; 
} 
void sigchld_handler(int sig){ 
pid_t pid; 
for(;;){ 
    pid=waitpid(0, NULL, WNOHANG); 
    if(pid==0) return; 
    if(pid<=0) { 
     if(errno==ECHILD) return; 
     perror("waitpid:"); 
     exit(EXIT_FAILURE); 
    } 
} 
} 

void usage(){ 
fprintf(stderr,"USAGE: sappartherroryst n\n"); 
fprintf(stderr,"n - number of Therrorysts\n"); 
} 

void therroryst_work(){ 
int s,k,t; 
srand(getpid()); 
s = rand_range(SIGRTMIN, SIGRTMAX); 
t = rand_range(10, 20); 
k = t; 
if(sethandler(disarming_handler, s)){ 
    perror("Seting therroryst handeler"); 
    exit(EXIT_FAILURE); 
} 

fprintf(stderr, "[%d] I am therroryst. My disarming signal is [%d]. I will wait [%d] Sec.\n", getpid(), s, t); 
while(k>0) { 
    k=sleep(k); 
    if(disarming_signal == s){ 
     fprintf(stderr, "I got signal [%d]\n.",disarming_signal); 
     return ; 
    } 
} 
fprintf(stderr, "[%d] KABOOM\n",getpid()); 
exit(EXIT_SUCCESS); 
} 
void create_therrorysts(int n){ 
while(n-->0){ 
    switch(fork()) { 
     case 0: 
      therroryst_work(); 
      exit(EXIT_SUCCESS); 
     case -1: 
      perror("Fork():"); 
      exit(EXIT_FAILURE); 
    } 
} 
} 
void sapper_work(){ 
int sig_dis, i; 
struct timespec t, tn = {1,0}; 
fprintf(stderr,"[%d] I am sapper.\n", getpid()); 
for(i=0;i<10;i++){ 
    for(t=tn;nanosleep(&t,&t);); 
    sig_dis = rand_range(SIGRTMIN, SIGRTMAX); 
    if(kill(0, sig_dis)<0){ 
     perror("Disarming_send\n"); 
     exit(EXIT_FAILURE); 
    } 

fprintf(stderr,"I sended signal [%d].\n",sig_dis); 
disarming_signal = sig_dis; 
} 
fprintf(stderr, "end of sending"); 
exit(EXIT_SUCCESS); 
} 

void create_sapper(){ 
switch(fork()) { 
    case 0: 
     sapper_work(); 
     exit(EXIT_SUCCESS); 
    case -1: 
     perror("Fork():"); 
     exit(EXIT_FAILURE); 
} 
} 
int main(int argc, char** argv){ 
int n; 
pid_t pid; 

if(argc != 2){ 
    usage(); 
    return EXIT_FAILURE; 
} 
n = atoi(argv[1]); 

if(n <= 0){ 
    usage(); 
    return EXIT_FAILURE; 
} 

if(sethandler(sigchld_handler, SIGCHLD)) { 
    perror("Seting parent SIGCHLD:"); 
    exit(EXIT_FAILURE); 
} 
create_therrorysts(n); 
create_sapper(); 
sleep(5); 
for(;;) { 
    if(sethandler(SIG_IGN, disarming_signal)){ 
     perror("Seting parent disarming111"); 
     exit(EXIT_FAILURE); 
    } 
} 

for(;;){ 
    pid=wait(NULL); 
    if(pid<0) 
     switch (errno){ 
      case ECHILD: 
       return EXIT_SUCCESS; 
      case EINTR: 
       continue; 
      default: 
       perror("wait:"); 
       exit(EXIT_FAILURE); 
     } 
} 

return EXIT_SUCCESS; 
} 
+0

Не используйте printf() в обработчике сигналов. Это не сигнал безопасный. – wildplasser

+0

Да, вы правы, но даже без этого есть проблема, о которой я упомянул. –

ответ

2

У вас есть сон (5) после создания_sapper и перед sethandler (IGN). Это означает, что очень вероятно, что сигнал будет отправлен до того, как ваш основной процесс проигнорирует его.

EDIT: Добавление комментария от Джонатана Леффлера в этот ответ, как это в равной степени (или даже более) важно:

Там также проблема с установкой обработчика сигнала, даже если положить сон() после этого цикла - родитель не видит, что ребенок выбирает как disarm_signal.

+1

Существует также проблема с настройкой обработчика сигнала, даже если вы положили sleep() после этого цикла - родитель не видит, что ребенок выбирает как «disarming_signal». –

+0

Да, хороший улов. Это, возможно, даже большая проблема, чем сон. – kaylum

+0

Я думал: скорее всего, disarm_signal будет установлен на случайный сигнал после сна, потому что без него я получаю обработку из сигнала ранга (начальное значение disarm_signal) –

Смежные вопросы