У меня есть программа (A), которая запускает другую программу (B).
Я хочу, чтобы каждый раз, когда B получал сигнал A, отправлял этот сигнал B и всем дочерним процессам B. Я действительно не знаю, как реализовать несколько вещей здесь:
1). Как определить, что сигнал был отправлен на B?
2). Как сохранить этот сигнал в переменной?
3). Как мне зациклить, пока B не станет живым?
int main() {
pid_t pid = fork();
int32_t num = 0;
if (pid == 0) {
static char *argv[] = {"main", NULL};
execv(argv[0], argv); //start program B
}
else{
while(/*B is alive*/){
//if program B receives signal
//I want to send this signal to B and all child processes,
//cause B doesn't handle any signals
if (/*B receives signal*/){
//save this signal to num.
kill(pid, num); //???
//send signal to parent
//useless cause it was already send to B?
fp = popen((("pgrep -P ") + string(num)).c_str(), "r");
//pgrep all child processes
std::vector<int> children;
while (fgets(buf, 128, fp) != NULL) //getting child pid
children.push_back(stoi(string(buf)));
for(auto a : children)
kill(a, num); //send signal to child
}
}
}
return 0;
}
Боюсь, ваш вопрос действительно слишком широкий и затрагивает слишком много тем. Я все равно постараюсь помочь, если это возможно.
Об обработке сигналов. Я обычно запускаю отдельный поток в моей программе, который просто посвящен обработке сигналов. Таким образом, я не буду «мешать» основному исполнению.
О том, как обрабатывать сигналы, просмотрите следующий фрагмент кода:
void * threadSignalHandler (){
int err, signo;
for (;;) {
err = sigwait(&mask, &signo);
if (err != 0) {
syslog(LOG_ERR, "sigwait failed");
exit(1);
}
switch (signo) {
case SIGHUP:
//Do your stuff here
break;
case SIGTERM:
//Do your stuff here
break;
default:
syslog(LOG_INFO, "unexpected signal %d\n", signo);
break;
}
}
return(0);
}
Опять же, как пояснено, я обычно создаю новый основной поток и делаю это следующим образом:
int err;
pthread_t tid;
/*
* Restore SIGHUP default and block all signals.
*/
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err_quit("%s: can′t restore SIGHUP default");
sigfillset(&mask);
if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
err_exit(err, "SIG_BLOCK error");/*
* Create a thread to handle SIGHUP and SIGTERM.
*/
err = pthread_create(&tid, NULL, threadSignalHandler, 0);
if (err != 0)
err_exit(err, "can′t create thread");
Итак, чтобы ответить на ваши 3 вопроса:
А) Используйте предоставленный мною код, он протестирован и я знаю, что он работает.
Б) Просто
изменить обработчик потока, чтобы сохранить полученный сигнал (переменная
Signo)
C) Пожалуйста, посмотрите здесь, есть консолидированные способы сделать
это, согласно стандартам posix
(Проверьте, существует ли процесс, учитывая его pid)
Других решений пока нет …