Здесь немного потеряно.Я реализую свою собственную оболочку, и одна из функций, которые мне нужно реализовать, - игнорировать ctrl + c и ctrl + z, когда нет запущенных дочерних процессов, но когда запущены дочерние процессы (например, sleep 5), тогдаон должен убить эти процессы.
Мне удалось успешно заблокировать SIGINT и SIGTSTP, используя маску в родительском элементе, вот так:
if ((sigemptyset(&intmask) == -1) || (sigaddset(&intmask, SIGINT) == -1) || (sigaddset(&intmask, SIGTSTP) == -1)) {
perror("invalid failed to initialize signal mask");
exit(EXIT_FAILURE);
}
signal(SIGUSR1, int_handler);
if (sigprocmask(SIG_BLOCK, &intmask, NULL) == -1) {
perror("invalid unable to block SIGINT");
exit(EXIT_FAILURE);
}
Затем в дочернем элементе я отправляюSIGUSR1
signal:
if (fork() == 0) {
kill(cmd_group->ppid, SIGUSR1);
}
Который вызывает обработчик сигнала:
void int_handler(int signum) {
if (signum == SIGUSR1) {
sigprocmask(SIG_UNBLOCK, &intmask, NULL);
}
}
Кажется, что он вызывает обработчик сигнала, когда я запускаю sleep 5
, но процесс незаканчивается ctrl + c.Я также должен отметить, что дочерние процессы находятся в своей собственной группе процессов, которая отличается от родительской.
Так почему же здесь не разблокируются SIGINT и SIGTSTP?
РЕДАКТИРОВАТЬ:
Почитав о различиях между игнорированием и блокировкой сигналов, я решил, что лучше игнорировать SIGINT и SIGTSTP в родительском элементе с помощью обработчика SIG_IGN
.
И затем возврат к SIG_DFL
у ребенка:
Родитель:
int main(int argc, char* argv[]) {
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
...
}
Ребенок:
if (fork() == 0) {
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
// execute commands
}
Для SIGINT он выполняет желаемое поведение: игнорирует в родительском и работает в дочернем.
Однако для SIGTSTP, когда я пытаюсь завершить дочерний процесс, такой как sleep 5
, он вызывает егонавсегда висеть (даже не возвращается из сна).
Что может быть причиной этого?