Обращение с процессами-«сиротами», описанное выше, показано на примере программы из листинга 34.7. После установки обработчиков для сигналов SIGHUP и SIGCONT
После создания всех потомков родитель останавливается на несколько секунд, чтобы дать им возможность запуститься
Листинг 34.7. Сигнал SIGHUP и «осиротевшая» группа процессов
pgsjc/orphaned_pgrp_SIGHUP.c
#define _GNU_SOURCE /* Получаем объявление strsignal() из
#include
#include
#include "tlpi_hdr.h"
static void /* Обработчик сигнала */
handler(int sig)
{
sig, strsignal(sig)); /* НЕБЕЗОПАСНО (см. подраздел 21.1.2) */
}
int
main(int argc, char *argv[])
{
int j;
struct sigaction sa;
if (argc < 2 || strcmp(argv[1], "-help") == 0)
usageErr("%s {s|p}…\n", argv[0]);
setbuf(stdout, NULL); /* Отключаем буферизацию стандартного вывода */
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
errExit("sigaction");
if (sigaction(SIGCONT, &sa, NULL) == –1)
errExit("sigaction");
printf("parent: PID=%ld, PPID=%ld, PGID=%ld, SID=%ld\n", (long) getpid(),
(long) getppid(), (long) getpgrp(), (long) getsid(0));
/* Создаем по одному потомку для каждого аргумента командной строки */
switch (fork()) {
case –1:
errExit("fork");
case 0: /* Потомок */
printf("child: PID=%ld, PPID=%ld, PGID=%ld, SID=%ld\n",
(long) getpid(), (long) getppid(),
(long) getpgrp(), (long) getsid(0));
if (argv[j][0] == 's') { /* Останавливаем по сигналу */
printf("PID=%ld stopping\n", (long) getpid());
} else { /* Ждем сигнала */
alarm(60); /* Завершаемся, если не получили сигнал SIGHUP */
printf("PID=%ld pausing\n", (long) getpid());
}
_exit(EXIT_SUCCESS);
default: /* Родитель идет дальше по циклу */
break;
}
}
/* Родитель переходит сюда после создания всех потомков */
printf("parent exiting\n");
}
pgsjc/orphaned_pgrp_SIGHUP.c
Следующая сессия командной строки демонстрирует результаты двух запусков программы из листинга 34.7:
$ echo $$
4785
$ ./orphaned_pgrp_SIGHUP s p
parent: PID=4827, PPID=4785, PGID=4827, SID=4785
child: PID=4828, PPID=4827, PGID=4827, SID=4785
PID=4828 stopping
child: PID=4829, PPID=4827, PGID=4827, SID=4785
PID=4829 pausing
parent exiting
$ PID=4828: caught signal 18 (Continued)
PID=4828: caught signal 1 (Hangup)
PID=4829: caught signal 18 (Continued)
PID=4829: caught signal 1 (Hangup)
$ ./orphaned_pgrp_SIGHUP p p
parent: PID=4830, PPID=4785, PGID=4830, SID=4785 child: PID=4831, PPID=4830, PGID=4830, SID=4785
PID=4831 pausing
child: PID=4832, PPID=4830, PGID=4830, SID=4785
PID=4832 pausing
parent exiting
При первом запуске в группе, которая должна стать «сиротой», создается два потомка: один сам себя останавливает, второй приостанавливается (в этом случае приглашение командной строки отображается посреди вывода потомков, поскольку командная оболочка замечает, что родитель уже завершился). Как можно заметить, после завершения родителя оба дочерних процесса получают сигналы SIGCONT и SIGHUP. При втором запуске снова создается два потомка, но на этот раз ни один из них не останавливается; благодаря этому завершение родителя не приводит к отправке сигналов.
«Осиротевшие» группы процессов и сигналы SIGTSTP, SIGTTIN и SIGTTOU
«Осиротевшие» группы сигналов также влияют на семантику доставки сигналов SIGTSTP, SIGTTIN и SIGTTOU.