2012-02-15 2 views
2

Цель этой программы - развить вилку и иметь дочерний сон, пока родительские петли бесконечно ждут прерывания. Когда я нажимаю^C, он вызывает функцию void parent. Однако эта часть работает, сообщение от kill (pid, SIGALRM) не работает. Я проверил и pid - это правильный идентификатор процесса для ребенка.C++ Process fork and sigalarm

Я искал какое-то время, но я не нашел, что я делаю неправильно. Я использовал kill (pid, SIGALRM) раньше от дочернего процесса родителя, но я не могу понять, почему это не работает ..

#include <signal.h> 
#include <unistd.h> 
#include <iostream> 
#include <sys/types.h> 
#include <sys/wait.h> 

using namespace std; 

int pid; 

void parent (int sig) 
{ 
     kill (pid, SIGALRM); 
     cout << "I'm a parent " << getpid() << " My child is " << pid << endl; 
} 

void child (int sig) 
{ 
     cout << "I am " << getpid() << "my parent is " << getppid()<< endl; 
     cout << "Use ctrl+backslash to actually end the program" << endl; 
} 
int main() 
{ 
     pid = fork(); 
     if(pid == 0) 
     { //Child process 
       cout << "Child pid = " << getpid() << " Waiting for interrupt." << endl; 
       (void) signal (SIGALRM, child); 
       pause(); 
     } 
     else if(pid > 0) 
     { //Parent 
       sleep(2); 
       cout << "child pid = " << pid << endl; 
       struct sigaction act; 
       act.sa_handler = parent; 
       sigemptyset (&act.sa_mask); 
       sigaction (SIGINT, &act, 0); 
       while(1) 
       { 
         sleep (1); 
       } 
     } 
     return 0; 
} 
+1

Какой выход и на какой ОС вы это делаете? Кроме того, будучи педантичным, эти обработчики сигналов должны быть определены с помощью C-связи. (Т.е., помещаем их внутрь внешних блоков «C») – Arafangion

+0

Также, как вы знаете, что iostreams безопасны в использовании в обработчике сигналов? Мне интересно, если это дубликат http://stackoverflow.com/questions/7623401/override-ctrl-c (Но даже если это так, я думаю, что этот вопрос заслуживает того, чтобы оставаться как есть) – Arafangion

+0

Я использую Fedora 15 . Вывод, который я получаю: 'Дочка с Pid = 23779 Ожидание interrupt.' ' дочернего процесса = 23779' '^ CI'm родитель 23778 Мой ребенок 23779' '^CI'm родитель 23778 My child is 23779' '^ \ Quit (core dumped)' И спасибо за блок extern C, я никогда не использовал его до – OrangeGrover

ответ

0

Хорошо, так что я понял, проблема.
Когда я нажимал^C, он прерывал прерывание в основном процессе, но убивал дочерний процесс. Когда я запускал system("ps") изнутри программы, он показал, что процесс a.out для ребенка не работает. Чтобы исправить это, я добавил следующее к процессу ребенка:

struct sigaction act; 
act.sa_handler = CHILD_PRESERVER; 
sigemptyset (&act.sa_mask); 
sigaction (SIGINT, &act, 0); 

Где CHILD PRESERVER была фиктивная функция, которая не сделала ничего, кроме держать его в живых.

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

0

Вы можете сделать то же самое, как ваш sigaction решение только с помощью signal(SIGINT, SIG_IGN);

Дело в том, что споткнулся вас изначально (и часто спотыкаются новых программистов, занимающихся Ctrl-C и сигналов) является то, что Ctrl-C посылает сигнал к ПРОГРАММНОЙ ГРУППЕ, а не к одному процессу - каждый процесс в группе получит сигнал. Группа процессов, на которую отправляется сигнал, является группой процесса переднего плана терминала.

Таким образом, это дает вам множество способов борьбы с прерываниями ctrl-C/control. У каждого процесса можно установить собственный обработчик SIGINT (как вы это сделали). Или вы можете тщательно управлять своими группами процессов, помещая детей в свою группу процессов (которая обычно не будет группой процессов переднего плана), поэтому они не получат сигнал в первую очередь.

Управление группами процессов с помощью системного вызова setpgrp (2)/setpgid (2).