TIP #121: Controlled Application Shutdown via Tcl_Exit
_____________________________________________________________________________
TIP:	121
Title:	Controlled Application Shutdown via Tcl_Exit
Version:	$Revision: 1.8 $
Authors:	Joe Mistachkin <joe@mistachkin.com>
State:	Final
Type:	Project
Tcl-Version:	8.5
Vote:	Done
Created:	Thu Dec 05 00:00:00 UTC 2002
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.
_____________________________________________________________________________
Colophon
TIP AutoGenerator - written by Donal K. Fellows