<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Library Exception Propagation Support</title>
</head>

<body>

<p>Doc. no.&nbsp;&nbsp; WG21/N2061=06-0131<br>
Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-09-08<!--webbot bot="Timestamp" endspan i-checksum="12594" --><br>
Project:&nbsp;&nbsp;&nbsp;&nbsp; Programming Language C++<br>
Reply to:&nbsp;&nbsp; Beman Dawes &lt;<a href="mailto:bdawes@acm.org">bdawes@acm.org</a>&gt;</p>

<h1>Library Exception Propagation Support</h1>

<p>This paper is in two parts:</p>

<ul>
  <li>Part one proposes adding <a href="#Part-One">exception propagation from 
  threads</a> to the threading library currently under consideration by the 
  Library Working Group. It is applicable regardless of the particulars of the 
  eventual threading library, and regardless of the implementation technique. 
  Part one may be superceded by similar facilities in thread library proposals 
  from others, but still serves as the motivation for part two. <br>
&nbsp;</li>
  <li>Part two proposes <a href="#Part-Two">library facilities needed to implement exception 
  propagation</a> in general and part one in particular. It is required to implement 
  part one under the current language rules, but is also useful outside of a 
  threading context. It is possible that part two could be 
  superceded by changes to the core language. If that happens, part two will be 
  withdrawn.</li>
</ul>

<p>The proposals in this paper are preliminary, and intended to put the issues 
on the table for further discussion.</p>

<h2><a name="Part-One">Part One</a>: Exception propagation from threads</h2>

<h3>Motivation</h3>

<p>In a thread of execution other than main(), what is useful yet safe behavior  if no matching exception handler is found 
after an exception is thrown?</p>

<p>Users of the Boost threading library, which does not currently do anything 
special with exceptions, have asked time-and-time again that the exception to be 
caught by the thread library mechanism and saved, and then 
re-thrown by the thread object's <code>join()</code> function or equivalent.</p>

<h3>Discussion</h3>

<p>Within a thread of execution, an exception will presumably cause a search for 
an exception handler as in any C++ program. Absent any thread library support 
for exception propagation, if no 
matching exception handler is found within the thread of execution, then <code>std::terminate()</code> will be 
called (15.3/9).</p>

<p>But just as in single-thread programs, it is highly desirable that 
exceptions propagate from a function to its caller. Because a thread's 
processing function is in a different thread of execution from its joining function doesn't change that. If exceptions do not propagate out of 
a thread of execution to its joining function, programmers are forced to construct ad hoc 
error recovery techniques of the worst kind, such as catching exceptions 
themselves and converting them to error codes (which are too often ignored by 
the joiner, with disastrous effects).</p>

<h3>Requirements</h3>

<ol>
  <li>An exception is never ignored; if no handler is found, if the thread of 
  execution is never joined, or if the thread of execution is detached, <code>std::terminate()</code> 
  is called.</li>
</ol>

<h3>Desirable, but not absolute requirements</h3>

<ol>
  <li>The exact exception type is propagated and the exact type can be caught 
  without slicing. See <a href="#program">example program</a>, and note that 
  catch #1 is desired to work.&nbsp; The proposed library solution does achieve 
  this.</li>
  <li>Works for both Standard Library and user-declared types. The proposed 
  library solution does achieve this.</li>
  <li>Works for all types, with no need for a common base class or special 
  exception launcher. Only a core language solution can achieve this.</li>
</ol>

<h3>Interaction with other proposals</h3>

<p>Proposals dealing with a C++ memory model that supports multi-threading will 
presumable change 15.3, Handling an exception, paragraph 9 as indicated:</p>
<blockquote>

<p>If no matching handler is found in <strike><font color="#FF0000">a program</font></strike>
<u><font color="#008080">the current thread of execution</font></u>, the 
function <code>std::terminate()</code> is called; whether or not the stack is 
unwound before this call to std::terminate() is implementation-defined (15.5.1).</p>
</blockquote>

<h3>Part One: Proposed changes</h3>

<p>Add&nbsp; a class <code>thread_exception_error</code> derived from <code>std::_runtime_error</code>, 
details to be supplied.</p>
<p>To the launcher function, add:</p>
<blockquote>
<p><i>Effects:</i> If an exception is thrown by the thread function, and the 
thread has not been detached, the exception is caught and saved (see join and 
destructor). Otherwise, <code>std::terminate()</code> is called.</p>
</blockquote>
<p>To the join function, add:</p>
<blockquote>
  <p><i>Throws:</i> If an exception from the thread function has occurred:</p>
  <ul>
    <li>If the exception was 
  of a type derived from <code><a href="#Proposed-2">tr2::cloneable</a></code>, 
  a copy of the originally thrown object.</li>
    <li>Otherwise, an object of type <code>std::thread_exception_error</code>.</li>
  </ul>
</blockquote>
  <p>To the thread destructor, add:</p>
<blockquote>
  <p><i>Effects:</i> If the thread object's thread-of-execution ended with an 
  uncaught exception 
  and the join function has not been called, call <code>std::terminate()</code>.</p>
</blockquote>
<h3>Open Issues</h3>
<ul>
  <li>Is a <code>nothrow</code> version of <code>join()</code> needed?</li>
  <li>Is <code>bool exception_pending() const</code> needed?</li>
  <li>Is getting a pointer to a pending exception needed?</li>
  <li>What happens if an exception is thrown by joining thread before join 
  reached?</li>
  <li>What happens if there are multiple pending exceptions for several joins?</li>
  <li>What happens on a join_all if multiple pending exceptions?</li>
  <li>Should exception propagation be mandatory or optional?</li>
</ul>
<hr>

<h2><a name="Part-Two">Part Two</a>: Exception propagation mixin</h2>

<p>Implementation of exception propagation requires two actions not directly 
supported by 
the C++03 exception handling mechanism:</p>

<ul>
  <li>It must be possible to allocate and create a copy an object, knowing only 
  its base class and not knowing its actual derived type.<br>
&nbsp;</li>
  <li>It must be possible to throw an object, knowing only its base class and 
  not knowing its actual derived type.</li>
</ul>

<p>There are three known approaches:</p>

<ol>
  <li>Language changes to allow cloning and throwing objects knowing only their 
  base class.<br>
&nbsp;</li>
  <li>A library based approach, requiring exceptions that may be propagated 
  according to their dynamic type be cloned and thrown by a special 
  library-supplied mechanism.<br>
&nbsp;</li>
  <li>A library based approach, requiring exceptions that may be propagated 
  according to their dynamic type be derived from a special library-supplied 
  mixin base class.</li>
</ol>

<p>The question of a core language approach versus a library approach was 
considered at the Redmond ad hoc threads meeting in August, 2006. There was consensus 
for going forward with both core language support and library support. If core 
language support is accepted, the library approach may still be of some value 
for C++03 compilers, and any cases not covered by core language support.</p>

<p>This proposal  relies on a library solution to achieve the desired &quot;join 
re-throws&quot; behavior.</p>

<h3>Part Two: <a name="Proposed-2">Proposed</a> changes</h3>

<p>To a header to be decided, add:</p>
<blockquote>
  <pre>namespace std
{
  namespace tr2
  {
    class cloneable
    {
    public:
      virtual cloneable *  clone_self() const;
      virtual void         throw_self() const;
      virtual ~cloneable();
    };
  }
}</pre>
  <p><b>Class <code>cloneable</code></b></p>
  <p>Class <code>cloneable</code> provides a mixin base class for objects that 
  need to clone themselves or throw themselves.</p>
</blockquote>
<blockquote>
  <pre>virtual cloneable * clone_self() const;</pre>
  <blockquote>
    <p><i>Returns:</i> <code>new cloneable(*this)</code></p>
  </blockquote>
  <pre>virtual void throw_self() const;</pre>
  <blockquote>
    <p><i>Throws: </i><code>*this</code></p>
  </blockquote>
</blockquote>

<h3>Rationale for mixin approach</h3>

<p>Users will need to write catch clauses for specific exception classes, both 
Standard Library and user-defined. To implement this behavior, it must be 
possible save and re-throw exceptions without knowing anything more than their 
base class. The <code>clone_self</code> and <code>throw_self</code> functions 
make this possible. Using a mixin base class allows degraded functionality even 
when the version of the Standard Library used does not itself use the mixin. It 
also works for user-defined exception types no derived from <code>std::exception</code>.</p>

<p>Pete Becker pointed out that the C++ runtime support knows the types, so it would be 
possible to add a clone operator to the language, and change the throw operation 
rules so the correct type is thrown on the rethrow. 
This current 
proposal is intended to work within the current language.</p>

<h3>Impact on the Standard</h3>

<p>This is a pure library proposal, suitable for TR2. It can be portably 
implemented with any C++03 compiler.</p>

<h2>Implementation experience with both parts 1 and 2</h2>
<p>Boost threads was hacked to provide the proposed functionality. The following 
<a name="program">program</a> illustrates the results:</p>
<blockquote>
  <pre>#include &lt;boost/thread/thread.hpp&gt;
#include &lt;boost/thread/mutex.hpp&gt;
#include &lt;boost/cloneable.hpp&gt;
#include &lt;stdexcept&gt;
#include &lt;iostream&gt;
boost::mutex cout_mutex; // cout race prevention;

class my_exception
  : public std::runtime_error, public virtual boost::cloneable
{
public:
  my_exception( const std::string &amp; s ) : runtime_error( s ) {}
  ~my_exception()                    {}
  my_exception *  clone_self() const { return new my_exception(*this); }
  void            throw_self() const { throw *this; }
};

class foo
{
  int m_argc;
public:
  foo( int argc ) : m_argc( argc ) {}
  void operator()()
  {
    boost::mutex::scoped_lock lock(cout_mutex);
    std::cout &lt;&lt; &quot;starting thread function&quot; &lt;&lt; std::endl;
    if ( m_argc &gt; 1 ) throw my_exception(&quot;\&quot;what-string\&quot;&quot;);
    std::cout &lt;&lt; &quot;normal return from thread function&quot; &lt;&lt; std::endl;
  }
};

int main( int argc, char * argv[] )
{
  foo child(argc);
  std::cout &lt;&lt; &quot;starting thread&quot; &lt;&lt; std::endl;
  boost::thread t(child);

  {
    boost::mutex::scoped_lock lock(cout_mutex);
    std::cout &lt;&lt; &quot;calling join&quot; &lt;&lt; std::endl;
  }
  try { t.join(); }

  catch ( const my_exception &amp; ex )  // catch #1
    { std::cout &lt;&lt; &quot;caught my_exception: &quot; &lt;&lt; ex.what() &lt;&lt; std::endl; }
  catch ( const std::exception &amp; ex )  // catch #2
    { std::cout &lt;&lt; &quot;caught std::exception: &quot; &lt;&lt; ex.what() &lt;&lt; std::endl; }

  std::cout &lt;&lt; &quot;exiting program&quot; &lt;&lt; std::endl;
  return 0;
}</pre>
</blockquote>
<p>When invoked with no arguments, the output is:</p>
<blockquote>
<pre>starting thread
starting thread function
normal return from thread function
calling join
exiting program</pre>
</blockquote>
<p>Invoked with any argument, the output is:</p>
<blockquote>
<pre>starting thread
starting thread function
calling join
caught my_exception: &quot;what-string&quot;
exiting program</pre>
</blockquote>

<h2>Acknowledgements</h2>

<p>An early version of this paper was discussed at the Redmond ad hoc threads 
meeting in August, 2006. Many participants contributed suggestions, and there 
was a strong consensus to go forward with a library based approach to the 
threading issues, and at the same time pursue both library and core language 
approaches to exception cloning and rethrowing. Alisdair Meredith suggested the 
mixin approach rather than changing <code>std::exception</code>, and provided an 
alternative approach that did not require changes to exception classes (but did 
require changes to code throwing exceptions.)</p>

<hr>
<p> Copyright Beman Dawes 2006</p>

</body>

</html>
