\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#121: Controlled Application Shutdown via Tcl\_Exit}
\date{December 05, 2002}
\author{Joe Mistachkin}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#121}&\textbf{Controlled Application Shutdown via Tcl\_Exit}\\\hline
Author&

Joe Mistachkin \tipmail{joe}{mistachkin.com}
\\
Created&Thursday, \(\text{5}^{\text{th}}\) December 2002\\
Type&Project\\
Tcl Version&\(8.5\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.8 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP will allow all applications to perform a controlled shutdown (or do nothing) in the event that \textit{Tcl\_Exit()} is called.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

For most applications written in C that use Tcl, calling the runtime \textit{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 \textit{Tcl\_Exit}.

\section{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 \textit{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 \textit{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.

\section{Proposed Changes}

First, this TIP proposes a new Tcl API function called \textit{Tcl\_SetExitProc()} or something similar. This function accepts a \textit{Tcl\_ExitProc} pointer and returns a \textit{Tcl\_ExitProc} pointer. The return value is the old exit proc pointer.

Second, the \textit{Tcl\_Exit()} Tcl API function would be modified to allow for the handler to be called.

Third, the documentation for \textit{Tcl\_Exit()} would be updated to include \textit{Tcl\_SetExitProc()} and a warning that any custom exit proc should NOT return.

\section{Tcl\_SetExitProc}
\begingroup\small\begin{verbatim}
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;
}
\end{verbatim}
\endgroup

\section{Tcl\_Exit}
\begingroup\small\begin{verbatim}
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!");
}
\end{verbatim}
\endgroup

\section{Example}
\begingroup\small\begin{verbatim}
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);
\end{verbatim}
\endgroup

\section{Reference Implementation}

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

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

\section{Consequences}

There is no change for current users of the \textit{Tcl\_Exit()} function, including the [exit] command, if \textit{Tcl\_SetExitProc()} is never called explicitly by the application.

\section{Copyright}

This document is hereby placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
