Advanced Programming in the UNIX Environment: Second Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Advanced Programming in the UNIX Environment: Second Edition [Electronic resources] - نسخه متنی

W. Richard Stevens; Stephen A. Rago

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



9.10. Orphaned Process Groups


We've mentioned that a process whose parent terminates is called an orphan and is inherited by the init process. We now look at entire process groups that can be orphaned and how POSIX.1 handles this situation.


Example

Consider a process that forks a child and then terminates. Although this is nothing abnormal (it happens all the time), what happens if the child is stopped (using job control) when the parent terminates? How will the child ever be continued, and does the child know that it has been orphaned? Chapter 10.)

  • The child sends itself the stop signal (SIGTSTP) with the kill function. This stops the child, similar to our stopping a foreground job with our terminal's suspend character (Control-Z).

  • When the parent terminates, the child is orphaned, so the child's parent process ID becomes 1, the init process ID.

  • At this point, the child is now a member of an

    orphaned process group . The POSIX.1 definition of an orphaned process group is one in which the parent of every member is either itself a member of the group or is not a member of the group's session. Another way of wording this is that the process group is not orphaned as long as a process in the group has a parent in a different process group but in the same session. If the process group is not orphaned, there is a chance that one of those parents in a different process group but in the same session will restart a stopped process in the process group that is not orphaned. Here, the parent of every process in the group (e.g., process 1 is the parent of process 6100) belongs to another session.

  • Since the process group is orphaned when the parent terminates, POSIX.1 requires that every process in the newly orphaned process group that is stopped (as our child is) be sent the hang-up signal (SIGHUP) followed by the continue signal (SIGCONT).

  • This causes the child to be continued, after processing the hang-up signal. The default action for the hang-up signal is to terminate the process, so we have to provide a signal handler to catch the signal. We therefore expect the printf in the sig_hup function to appear before the printf in the pr_ids function.


  • Here is the output from the program shown in Figure 9.11:

    $

    ./a.out
    parent: pid = 6099, ppid = 2837, pgrp = 6099, tpgrp = 6099
    child: pid = 6100, ppid = 6099, pgrp = 6099, tpgrp = 6099
    $ SIGHUP received, pid = 6100
    child: pid = 6100, ppid = 1, pgrp = 6099, tpgrp = 2837
    read error from controlling TTY, errno = 5

    Note that our shell prompt appears with the output from the child, since two processesour login shell and the childare writing to the terminal. As we expect, the parent process ID of the child has become 1.

    After calling pr_ids in the child, the program tries to read from standard input. As we saw earlier in this chapter, when a background process group tries to read from its controlling terminal, SIGTTIN is generated for the background process group. But here we have an orphaned process group; if the kernel were to stop it with this signal, the processes in the process group would probably never be continued. POSIX.1 specifies that the read is to return an error with errno set to EIO (whose value is 5 on this system) in this situation.

    Finally, note that our child was placed in a background process group when the parent terminated, since the parent was executed as a foreground job by the shell.


    Figure 9.10. Example of a process group about to be orphaned


    Figure 9.11. Creating an orphaned process group

    #include "apue.h"
    #include <errno.h>
    static void
    sig_hup(int signo)
    {
    printf("SIGHUP received, pid = %d\n", getpid());
    }
    static void
    pr_ids(char *name)
    {
    printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %d\n",
    name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO));
    fflush(stdout);
    }
    int
    main(void)
    {
    char c;
    pid_t pid;
    pr_ids("parent");
    if ((pid = fork()) < 0) {
    err_sys("fork error");
    } else if (pid > 0) { /* parent */
    sleep(5); /*sleep to let child stop itself */
    exit(0); /* then parent exits */
    } else { /* child */
    pr_ids("child");
    signal(SIGHUP, sig_hup); /* establish signal handler */
    kill(getpid(), SIGTSTP); /* stop ourself */
    pr_ids("child"); /* prints only if we're continued */
    if (read(STDIN_FILENO, &c, 1) != 1)
    printf("read error from controlling TTY, errno = %d\n",
    errno);
    exit(0);
    }
    }

    We'll see another example of orphaned process groups in Section 19.5 with the pty program.


      / 369