[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

General Programming Concepts: Writing and Debugging Programs


Process Duplication and Termination

Because all processes have at least one thread, creating (that is, duplicating) and terminating a process implies the creation and the termination of threads. This article describes the interactions between threads and processes when duplicating and terminating a process.

Read the following to learn more about process duplication and termination:

Forking

There are two reasons why AIX programmers call the fork subroutine:

  1. To create a new flow of control within the same program. AIX creates a new process.
  2. To create a new process running a different program. In this case, the call to the fork subroutine is soon followed by a call to one of the exec subroutines.

In a multi-threaded program, the first use of the fork subroutine, creating new flows of control, is provided by the pthread_create subroutine. The fork subroutine should thus be used only to run new programs.

The fork subroutine duplicates the parent process, but duplicates only the calling thread; the child process is a single-threaded process. The calling thread of the parent process becomes the initial thread of the child process; it may not be the initial thread of the parent process. Thus, if the initial thread of the child process returns from its entry-point routine, the child process terminates.

When duplicating the parent process, the fork subroutine also duplicates all the synchronization variables, including their state. Thus, for example, mutexes may be held by threads that no longer exist in the child process and any associated resource may be inconsistent.

It is strongly recommended to use the fork subroutine only to run new programs, and to call one of the exec subroutines as soon as possible after the call to the fork subroutine in the child process.

Fork Handlers

Unfortunately, the rule explained above does not address the needs of multi-threaded libraries. Application programs may not be aware that a multi-threaded library is in use and will feel free to call any number of library routines between the fork and the exec subroutines, just as they always have. Indeed, they may be old single-threaded programs and cannot, therefore, be expected to obey new restrictions imposed by the threads library.

On the other hand, multi-threaded libraries need a way to protect their internal state during a fork in case a routine is called later in the child process. The problem arises especially in multi-threaded input/output libraries, which are almost sure to be invoked between the fork and the exec subroutines to affect input/output redirection.

The pthread_atfork subroutine provides a way for multi-threaded libraries to protect themselves from innocent application programs which call the fork subroutine. It also provides multi-threaded application programs with a standard mechanism for protecting themselves from calls to the fork subroutine in a library routine or the application itself.

The pthread_atfork subroutine registers fork handlers to be called before and after the call to the fork subroutine. The fork handlers are executed in the thread that called the fork subroutine. There are three fork handlers:

Prepare The prepare fork handler is called just before the processing of the fork subroutine begins.
Parent The parent fork handler is called just after the processing of the fork subroutine is completed in the parent process.
Child The child fork handler is called just after the processing of the fork subroutine is completed in the child process.

The prepare fork handlers are called in last-in first-out (LIFO) order, whereas the parent and child fork handlers are called in first-in first-out (FIFO) order. This allows programs to preserve any desired locking order.

Process Termination

When a process terminates, by calling the _exit subroutine either explicitly or implicitly, all threads within the process are terminated. Neither the cleanup handlers nor the thread-specific data destructors are called.

The reason for this behavior is that there is no state to leave clean and no thread-specific storage to reclaim, because the whole process terminates, including all the threads, and all the process storage is reclaimed, including all thread-specific storage.

Related Information

Understanding Threads.

Threads-Processes Interactions Overview.

Signal Management.

Scheduling.

List of Threads-Processes Interactions Subroutines.


[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]