HPlogo HP-UX Process Management: White Paper > Chapter 1 Process Management

Process Termination

» 

Technical documentation

Complete book in PDF

 » Table of Contents

When a process finishes executing, HP-UX terminates it using the exit system call.

Circumstances might require a process to synchronize its execution with a child process. This is done with the wait system call, which has several related routines.

During the exit system call, a process enters the zombie state and must dispose of child processes. Releasing process and thread structures no longer needed by the exiting process or thread is handled by three routines -- freeproc(), freethread(), and kissofdeath().

This section will describe each process-termination routine in turn.

The exit System Call

exit() may be called by a process upon completion, or the kernel may have made the call on behalf of the process due to a problem.

If the parent process of the calling process is executing a wait(), wait3(), or waitpid(), it is notified of the calling process's termination. If the parent of the calling process is not executing a wait(), wait3(), or waitpid(), and does not have SIGCLD ( death of a child) signal set to SIG_IGN (ignore signal), the calling process is transformed into a zombie process. The parent process ID is set to 1 for all of the calling process's existing child processes and zombie processes. This means the process 1 (init) inherits each of the child processes.

Figure 1-16 Summary of the exit system call

[Summary of the exit system call]

exit() passes status to the system and terminates the calling process in the following manner:

  • Clear the process' STRC (process being traced) flag by calling STRC_EXIT(p,kt).

  • Issue a process-wide directive to reduce an exiting multi-threaded process to a single thread of execution. Clear the multi-threaded flag for non-vfork processes.

  • Set the process p_flag to SWEXIT to indicate it is exiting.

  • Set process to ignore signal information.

  • Make sure the "no swap" counter is balanced.

  • Determine whether the exiting process is a controlling process. If it has a controlling tty, send SIGHUP and free tty for another session.

  • Release memory-mapped semaphores.

  • Disarm all timers and clear any related pending siginfos.

  • Do exit processing for graphics and iomap driver, if needed.

  • If the process was created via vfork() release the virtual memory and return resources to the parent.

  • Cancel all the process's pending asynchronous I/O requests and sleep until all are completed.

  • Free up space taken by the table of pointers to file-descriptor chunks.

  • Release MQ resources, NFS lock manager resources, audit-control structures, and process-wide and thread copies of credentials.

  • Do exit processing for semaphores.

  • Destroy any adopted processes.

  • Search all processes for zombies whose p_dptr field is not set; send SIGCLD to the parent and wake it up, if parent has called wait().

  • Signal the process group that exit is causing it to become an orphan with stopped processes. Deal with orphaned process group and any children.

  • Notify init that zombies are waiting.

  • Unlink from active list of processes.

  • Unlink current thread from active list of threads and set the thread state.

  • Process enters SZOMB state, and thread enters TSZOMB state.

  • Choose which process to send SIGCLD. If exiting process is a daemon, make it a child of init.

  • Awaken init to start the cleanup process.

  • If vfork() created the process, reset vfork_state to VFORK_CHILDEXIT, to allow resume() to restore the parent.

  • Verify that the thread state is set to TSSLEEP.

  • Retain the "thread lock" across the context switch path. Both signal path and init process must wait until the last thread is non-TSRUNPROC.

  • Call swtch() to release the process lock.

wait System Call

From the user perspective, the wait system call is actually four different interfaces used to synchronize a child to parent process. All four versions call the wait1() routine, which does the actual work./

Figure 1-17 Process termination -- wait()

[Process termination -- wait()]

The following table summarizes the basic differences among the wait() functions. For further information, consult kern_exit.c, wait(2) manpage, and wait.h header file.

Table 1-8 User interfaces to the wait system call

InterfacePurpose
wait()Calls wait1() to determine if any zombie process are present; if not, wait1() sleeps. wait() determines which process is of interest based on the pid argument and passes it on to wait1(): -1, all processes>0, processes with process ID == pid
0, processes in same process group as caller<-1, processes with process group ID == -pid
Once wait1() returns, wait() passes the exit status of the terminated child back to the calling process.
waitpid()POSIX version of the wait() system call. It allows the caller to also wait on processes with the same group ID and translate information for wait1().
waitid()Suspends the calling process until one of its children changes state. It records the current state of a child in infop (passes signal information between threads). The id_type, which contains the set of processes that should receive the signal, can be one of the following:
P_PID, process id
P_PGID, process group id
P_ALL all processes
wait3()Almost identical to wait(); however, wait3() can be passed a WNOHANG flag through the argument options. If the child has not exited, the WNOHANG flag will not block if no one is waiting.

 

wait1() subroutine

wait1() searches for a terminated (zombie) child, to gather its status information and remove it. wait1() also looks for stopped (traced) and continued children, and passes back status from them to their parents. wait1() determines which process is interesting based on the pid argument passed. The following are some of the steps performed by wait1():

  • Hold the pm_sema to ensure that a process already checked does not become a zombie while other processes are being checked, thus resulting in a lost wakeup.

  • Find and count the step-children who do not belong to the parent process being waited on. If zombies, undebug them and signal their parents. If stopped, signal the step-parent.

  • Search all processes. This is mainly due to the fact SZOMB processes are no longer on the active process list.

  • While under the protection of an MP_PROCESS_LOCK, make sure that p_zombies_exist = 0.

  • If an SZOMB process is found, the entry is removed from any proc hash table (proc_unhash()) and the thread is deallocated (thread_deallocate()).

  • Call freeproc() to release the process structures SZOMB.

freeproc(), freethread(), and kissofdeath() Routines

The freeproc(), freethread(), and kissofdeath() routines complete the clean-up effort on behalf of wait1() for a terminating process

Figure 1-18 Process termination

[Process termination]

Table 1-9 Final process termination routines

RoutinePurpose
freeproc()

Called from wait1() to release process structures that zombie processes are no longer using. freeproc() performs the following steps:

  • Under the protection of an MP_PROCESS_LOCK, clear p_pl_flags.all, set p_stat to SUNUSED, and verify that p_sigwaiters is set to NULL.

  • Decrement the number of active proc table entries.

  • Add the child's rusage (sum of stats of the reaped child) structure to the parent..

  • Release the rusage data sturcture, process timers data, msginfo, and any queued.signals pending against the process.

  • Release the virtual address space.

  • Return the proc entry to the free list

freethread()

Called from wait1() to release the thread structure. freethread() performs the following steps:

  • Under the protection of an MP_PROCESS_LOCK, clear kt_cntxt_flags and set kt_stat to TSUNUSED.

  • Decrement the number of active thread table entries.

  • Clear the thread fields. If a thread was not cached, dismantle its uarea by calling kissofdeath().

  • Release the thread entry by calling link_thread_to_free-list().

kissofdeath()Called from freethread() and freeproc() to clear the kernel stack and uarea of a named process.