TIP:            121
Title:          Controlled Application Shutdown via Tcl_Exit
Version:        $Revision: 1.8 $
Author:         Joe Mistachkin <joe@mistachkin.com>
State:          Final
Type:           Project
Vote:           Done
Created:        05-Dec-2002
Post-History:   
Tcl-Version:    8.5

~ Abstract

This TIP will allow all applications to perform a controlled shutdown
(or do nothing) in the event that ''Tcl_Exit()'' is called.

~ Rationale

For most applications written in C that use Tcl, calling the runtime
''exit()'' function is normally a reasonable way to shutdown the
application.  Unfortunately, this is not always the case.
Applications written in other languages (and very complex C
applications) may have very specific application shutdown
requirements.  This is especially true in multi-threaded
environments.  The problem is further compounded by extensions that
use ''Tcl_Exit''.

~ Versus Exit Handlers

There are distinct advantages to using this method instead of using
normal exit handlers in some cases.  The normal exit handler cannot
defer (or in an emergency, prevent) the application shutdown because
''Tcl_Finalize()'' has already been called.  From the perspective of
the exit handler, we have no way of knowing what other exit handlers
have been called and/or their subsystems destroyed. In addition, even
if it could somehow cause ''Tcl_Finalize()'' to defer the application
shutdown, some or all of the other exit handlers may have already
been executed, which would leave the application in an inconsistent
state.  This relatively simple change allows the programmer to get
control very early during the application shutdown process.

~ Proposed Changes

First, this TIP proposes a new Tcl API function called
''Tcl_SetExitProc()'' or something similar.  This function
accepts a ''Tcl_ExitProc'' pointer and returns a ''Tcl_ExitProc''
pointer.  The return value is the old exit proc pointer.

Second, the ''Tcl_Exit()'' Tcl API function would be modified to
allow for the handler to be called.

Third, the documentation for ''Tcl_Exit()'' would be updated to
include ''Tcl_SetExitProc()'' and a warning that any custom exit proc
should NOT return.

~ Tcl_SetExitProc

|Tcl_ExitProc *
|Tcl_SetExitProc(proc)
|    Tcl_ExitProc *proc; /* new exit handler for app or NULL */
|{
|    Tcl_ExitProc *prevExitProc; /* return prev exit handler to caller */
|
|    Tcl_MutexLock(&exitMutex);
|    prevExitProc = appExitPtr; /* get old app exit ptr */
|    appExitPtr = proc; /* set new app exit ptr */
|    Tcl_MutexUnlock(&exitMutex);
|
|    return prevExitProc;
|}

~ Tcl_Exit

|void
|Tcl_Exit(status)
|    int status;			/* Exit status for application;  typically
|				 * 0 for normal return, 1 for error return. */
|{
|    Tcl_ExitProc *currentAppExitPtr;
|
|    Tcl_MutexLock(&exitMutex);
|    currentAppExitPtr = appExitPtr;
|    Tcl_MutexUnlock(&exitMutex);
|
|    if (currentAppExitPtr) {
|      /***********************************************************/
|      /* WARNING: This code SHOULD NOT return, as there is code  */
|      /*          that depends on Tcl_Exit never returning.      */
|      /***********************************************************/
|      currentAppExitPtr((ClientData) status);
|    } else {
|      Tcl_Finalize();
|      TclpExit(status);
|    }
|
|    Tcl_Panic ("exitProc returned!");
|}

~ Example

|void MyAppExitProc(ClientData clientData)
|{
|  /* #1. Perform application specific shutdown code...    */
|  /* #2. Wait for other threads to gracefully shutdown... */
|
|  exit(0);
|
|  return; /* We should never get here. */
|}
|
|
| ... sometime during application initialization ...
|
| /* from this point on MyAppExitProc will handle Tcl_Exit requests */
| Tcl_SetExitProc(MyAppExitProc);
|
| ... optionally, sometime later ...
|
| /* from this point on the old (default) handling will be used */
| Tcl_SetExitProc(NULL);

~ Reference Implementation

A patch that implements everything suggested in this TIP is available
at the URL:

http://sourceforge.net/tracker/index.php?func=detail&aid=649313&group_id=10894&atid=310894

~ Consequences

There is no change for current users of the ''Tcl_Exit()'' function,
including the [[exit]] command, if ''Tcl_SetExitProc()'' is never
called explicitly by the application.

~ Copyright

This document is hereby placed in the public domain.
