<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


<meta name="viewport" content="width=device-width, initial-scale=1">


<style>
pre {font-family: "Consolas", "Lucida Console", monospace; margin-left:20pt; }
code {font-family: "Consolas", "Lucida Console", monospace; }
pre > i   { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > i  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
pre > em  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > em { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
/*body { color: #000000; background-color: #FFFFFF; }*/

@media (prefers-color-scheme: dark) {
	body { background: #111; color:  #ccc; }
	a { color:  #38f; }
	a:visited { color:  #a4d; }
	.sect { color:  #ccc; }
}

@media (prefers-color-scheme: light) {
	body { background:  white; color: black; }
}

del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract  { margin-left: 2em; background-color: #F5F6A2;  border: 1px solid #E1E28E; }

p.function    { }
.attribute    { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

.editor { color: #4444BB; font-style: normal; background-color: #DDDDDD; }

tab { padding-left: 4em; }
tab3 { padding-left: 3em; }

.link { float: right }

blockquote.std    { color: #000000; background-color: #F1F1F1;  border: 1px solid #D1D1D1;  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;  color: #000000; background-color: #FFEBFF;  border: 1px solid #ECD7EC;  padding-left: 0.5em; padding-right: 0.5em; ; }
blockquote.stdins { text-decoration: underline;  color: #000000; background-color: #C8FFC8;  border: 1px solid #B3EBB3; padding: 0.5em; }
table.header { border: 0px; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table.poll { border: 1px solid black; border-spacing: 0px;  margin-left: 0px; font-style: normal; }
table { border: 1px solid black; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }
td { text-align: left;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }

.revision   { /*color: #005599;*/ }
.grammar { list-style-type:none }

</style>

<title>Not halting the program after detected contract violation</title>

</head>
<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>P2784R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2023-02-09</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td>SG21</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td>
		<!--<address>Gašper Ažman &lt;gasper dot azman at gmail dot com&gt;</address>
		<address>Joshua Berne &lt;jberne4 at bloomberg dot net&gt;</address>
		<address>Bronek Kozicki &lt;brok at spamcop dot net&gt;</address>-->
		<address>Andrzej Krzemieński &lt;akrzemi1 at gmail dot com&gt;</address>
    <!--<address>Ryan McDougall &lt;mcdougall dot ryan at gmail dot com&gt;</address>
		<address>Caleb Sunstrum &lt;caleb dot sunstrum at gmail dot com&gt;</address>-->
				
      </td>
  </tr>
</tbody></table>


<h1>Not halting the program after detected contract violation</h1>


<p> This paper explores the possibility of not stopping the program after a contract violation has been detected at run-time.
    This is a feature to be added to the contract support framework. </p>


<h2><a class="sect" id="mot">1. Motivation <span class="link">{mot}</span></a></h2>


<p> Contract annotations are tools for expressing what constitutes a program that is running against
    its specification ("specification" understood as information provided in contract annotations). 
    If a runtime check based on such annotation returns <code>false</code>, we can be sure that
    this is happening right now: the program runs against the specified intentions. If a program is
    let to continue at this point, one of the likely consequences is that it will either crash
    or start behaving in an unpredictable way (e.g. by hitting an undefined behavior at the language level):</p>
    
<pre>
int * p = 0;
[[assert: p != 0]];
return *p > 3; </em>// bad things!</em>
</pre>

<p> For this reason papers like <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> 
    suggest to immediately halt the program at this point which, while being a harsh reaction,
    gives a guaranteed repeatable result with an upper limit on the possible consequences.</p>
    
<p> While this seems a good default, there are situations where stopping the program this way is not the optimum solution.
    These include:</p>
    
<ol>
    <li>When there is an isolated subcomponent in a program, maybe relatively new, where we can be fairly 
        confident that a bug in the subcomponent will not affect the correctness of the remaining parts of 
        the program.</li>
    <li>A special case of the above is when we consider function <code>main()</code> as such submodule.
        We may know that a bug in function <code>main()</code> may not affect the correctness of the second
        call to <code>main()</code> if we somehow managed to restart it from within the program.</li>
    <li>In case of unit tests, we may deliberately violate the function contract in order to determine
        the existence of safety measures such as contract annotations.</li>
    <li>When the program has been running in production for a long while, and likely taken all the possible 
        control paths, we may be fairly confident that even if the program does not stick to its internal
        specification, it still behaves according to user expectations.</li>
</ol>

<p> The first three cases have one thing in common: while we do not want the program to halt, it is allowed,
    and even desired, to resume the program execution from a different place than where the contract violation
    was observed. In this paper we only focus on these use cases. This sounds like a job for the 
    exception handling mechanism. We consider it as one of the options, however this paper also proposes another.
    </p>


<h2><a class="sect" id="exc">2. Exceptions <span class="link">{exc}</span></a></h2>


<p> The problem of transferring control to a different location upon "failure" is addressed in 
    C++ by the exception handling mechanism. This mechanism blends nicely with other parts of the language
    by:</p>
    
<ul>
    <li>releasing all acquired resources by invoking class destructors,</li>
    <li>allowing the non-failure control path to be expressed cleanly, without any visible <code>if</code>-statements.</li>
    </ul>
    
<p> This is why 
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html"
       title="G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup, &ldquo;Support for contract based programming in C++&rdquo;">[P0542R5]</a>
    allowed a "mode" where upon a detected contract violation a programmer-installed violaiton handler is invoked,
    and this handler as one of possible opitons can throw an exception. This way we get a two-fold guarantee:
       </p>

<ul>
    <li>the code following the contract annotation is not executed (due to exception),</li>
    <li>control is transfered to a different place, where hopefully the program can recover.</li>
    </ul>
    
<p> This is also what <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
        title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>
    proposes under a new translation mode <strong>Eval_and_throw</strong>.</p>
    
<p> Using exceptions to recover from contract violations, however, is problematic for a number of reasons.</p>

<p> The first issue is conceptual. Exceptions were meant to handle the situation
    where a <strong>correct</strong> program responds in an exceptional way to an exceptional situation.
    This exceptional recovery still executes some code (primarily destructors) and the executed code also assumes
    that the program is correct and it has its own preconditions.</p>  

<p> Consider a class with an invariant expressed in the source code via preconditions.</p>

<pre>
class State 
{
  std::vector&lt;Column*&gt; _columns;
  unsigned _theColumn;

public:  
  bool invariant() const noexcept 
  {
    return _theColumn &lt; _columns.size() &amp;&amp; _columns[_theColumn] != nullptr;  
  }
  
  void alter() 
    [[pre: invariant()]]
    [[post: invariant()]];
  
  ~State() 
    [[pre: invariant()]] 
  {
     delete _columns[_theColumn];
  }
};
</pre>    

<p> If upon calling <code>state.alter()</code> its precondition is violated and this
    gets turned into an exception, during the stack unwinding we will need to call 
    the destructor of <code>state</code>. The destructor also has a precondition
    which would also be violated. This would trigger a second exception to be thrown,
    which in C++ normally results in calling <code>std::terminate</code>.    
    </p> 
    
<p> We could put it in another way: destructors also have preconditions, and they
    may call other funcitons with contract annotations. If any of these checks fail,
    we get a throwing destructor, which likely aborts the program.
    </p>
    
<p> The second issue is more pragmatic: the interaction with <code>noexcept</code>
    functions, which can also have contract annotations. If contract checks are 
    allowed to throw, we have a new question to answer, that 
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html"
       title="Andrzej Krzemieński, Gašper Ažman, &ldquo;Minimum Contract Support: either No_eval or Eval_and_abort&rdquo;"
       >[P2388R4]</a> doesn't have to answer: are contract conditions evaluated inside or outside the function
       &mdash; because now it becomes a visible property:
    </p>
    
<pre>
void fun() noexcept [[pre: false]];

void test()
{
  fun(); <em>// ok if precondition evaluated outside the function
         // std::terminate() if precondition evaluated inside the function</em>
}
</pre>

<p> Note that even if we said that the precondition must be evaluated outside the function,
    this does not solve the problem of reporting contract violaiton via throw from
    nested <code>noexcept</code> funcitons:</p>

<pre>
void fun() noexcept [[pre: false]];

void gun() noexcept
{
  fun();
}

void test()
{
  gun();  <em>// std::terminate()</em>
             
  void(*pf)() noexcept = &amp;fun;
  pf();   <em>// std::terminate()</em>
}
</pre>

<p> And in fact the issue is bigger than just <code>noexcept</code> functions. What should operator <code>noexcept</code> return?</p>

<pre>
void fun() noexcept [[pre: false]];

constexpr bool mystery = noexcept(fun());
</pre>

<p> Remember that operator <code>noexcept</code> tests full expressions along with invisible things like conversions and destructors.
    Should its value be dependent on the translation mode?
    </p>
    
<p> The scope of the poblem is even wider. It is not limited to functions declared <code>noexcept</code> 
    but also to functions that provide a no-fail guarantee, even if this is not statically checkable.
    This is how exception-safety (or failuer-safety) guarantees work: you can only provide a strong (commit or rollback)
    guarantee when you know that some operations never throw. When upon contract violation
    they nonetheless start to throw, no funciton can provide the declared level of exception safety.
    One could argue that if a precondition is violated, by definition, no guarante is provided.
    But on the other hand, one of the goals of contracts is to offer some guarantees even if the contact
    is violated.    
    </p>    

<p> The third issue stems from the fact that a huge fraction of C++ programs is compiled with exceptions disabled.
    Yet, these programs have the same problem to solve: how not to halt the program upon contract violation.
    </p>
  

 
 
<h2><a class="sect" id="abo">3. Aborting a component <span class="link">{abo}</span></a></h2>

<p> As a potential solution to the above problem we propose a mechanism that is harsher than 
    stack unwinding, but softer than <code>std::abort()</code>. In fact we are proposing a stricter
    and simpler version of the <code>setjmp</code>/<code>longjmp</code> mechanism. It is composed
    of two proposed Standard Library functions with special powers:
    </p>
    
<pre>
template &lt;invokable F&gt;
void abortable_component(F&amp;&amp; f);
</pre>

<p> This invokes the passed function <code>f</code> in almost a regular way, except that it is treated
    as "being executed in a separate component" as described below. Function <code>std::abortable_component</code>
    is exception-neutral: whatever the evaluation of <code>f()</code> throws is thrown out of function
    <code>std::abortable_component</code>. The goal of this function is to instruct the compiler what
    the programmer considers a component boundary.</p>
    
<pre>
[[noreturn]] void abort_component() noexcept;
</pre>

<p> Calling this function initiates the process of leaving the function call stack, without calling 
    destructors of automatic objects and function parameters, until a component boundary, indicated
    by <code>std::abortable_component</code> is reached. Then the program resumes just after the call to
    <code>std::abortable_component</code>. If no component boundary is found in the call stack then <code>std::abort</code>
    is called. Example:
    </p>
 
<pre>
struct Guard {
  ~Guard() { std::printf("A"); }
};

int fun() {
  Guard g;
  std::abort_component();          <em>// (2) abort sequence starts</em>
  std::printf("B");                <em>// (3) this is skipped, "B" is never printed</em>
}                                  <em>// (4) destructor is skipped, "A" is never printed</em>
 
int main() {
  std::abortable_component(&amp;fun);  <em>// (1) launching `fun` as a subcomponent</em>
  std::printf("C");                <em>// (5) getting out of subcmponent, "C" is printed</em>
}
</pre> 
 
<p> We could say that this mechanism is similar to stack unwinding except that:</p>

<ul>
  <li>there is no exception type matching, as there are no exception objects involved;</li>
  <li>no destructors &mdash; or other functions, such as copying exception objects &mdash; are invoked.</li>
</ul>

<p> Alternatively, we could say that this is like <code>setjmp</code>/<code>longjmp</code>,
    except that the proposed approach is more structured: subcomponents have to nest.
    There is also no way to convey any information other than the fact that we are aborting.
    And there is no undefinded behavior related to skipping destructors.    
    </p>

 

<h2><a class="sect" id="dis">4. Discussion<span class="link">{dis}</span></a></h2>


<p> As one can easily observe, aborting a component can easily cause resource leaks,
    as destructors of automatic objects and function parameters are not executed.
    It may be more than just leaks. Not calling the destructor of <code>scoped_lock</code>
    can cause concurrency issues in other parts of the program.
    However, we are talking about a tool for minimizing damage in a desperate situation:
    </p>
    
<ul>
    <li>a program cannot afford to halt,</li>
    <li>a program has a proof that it behaves incorrectly.</li>
</ul>

<p> The goal is no longer to get everything right, but to minimize damage.
    Continuing without cleanup can cause further bugs, but so can continuing 
    after a detected bug. This will be a dangerous feature, not recommended to
    be used for other situations.</p>
    
<p> Putting <code>std::abortable_component</code> in the program would mean that the
    programmer considers it reasonably safe to continue the execution of the program
    from that point even if arbitrary parts of the called function were skipped.
    This could be an option when invoking a "plugin" that is an optional part of the progam,
    experimental and not required to fulfil the main program task.</p>
    
<p> The other part of the interface &mdash; function <code>std::abort_component()</code>
    would not even have to be exposed to programmers. For the purpose of the 
    contract support framework it would be enough to say that in <strong>Eval_and_abort</strong>
    translation mode, when the predicate evaluates to <code>false</code> the effect is as if 
    <code>std::abort_component()</code> was called. We wouldn't need a third translation mode,
    the effect of not aborting would be achieved by putting <code>std::abortable_component</code>
    in your program. Thus, when you want your program not to abort upon contract violation,
    you have to indicate a place (or places) where it is safe to resume the program from.</p>
    
<p> This feature can be intorduced after the MVP in a backward-compatible fassion.
    For the MVP we can simply say that upon contract violation <code>std::abort()</code>
    is called. Then, after the MVP change it to calling <code>std::abort_component()</code>,
    which is indistinguishable from <code>std::abort()</code> as long as you have no
    call to <code>std::abortable_component()</code> in the program.</p>
    
<p> Finally, the proposed interface is very modest: there is no information conveyed
    about the point of and the reason for calling <code>std::component_abort()</code>.
    There is not information whether we returned normally or via the abort from
    <code>std::abortable_component()</code>. The mechanism could be extended to satisfy these expectations.
    However, the goal of this paper is to show the main idea behind the feature.
    Similarly, if this mechanism is used to handle contract violation, it could be combined
    with logging the information about the point of failure before calling 
    <code>std::abort_component()</code>.
    </p>
    

<h3><a class="sect" id="dis.use">4.1. Use cases<span class="link">{dis.use}</span></a></h3>

<p> The use cases serviced by this feature.</p>


<h4><a class="sect" id="dis.use.plu">4.1.1 Plugins<span class="link">{dis.use.plu}</span></a></h4>

<p> Suppose function <code>solve()</code> evaluates one of the user-prvided pugins.
    it may have a bug, but if it fails &mdash; even if it leaked some resources &mdash; 
    the rest of the program, or other user plugins
    may still work fine. </p>
    
<pre>
int solve(); <em>// user plugin </em>

bool call_user_plugin = true; <em>// my flag for protecting against calling plugin twice, if it is proven buggy </em>

std::optional&lt;int&gt; fun()
{
  std::optional&lt;int&gt; solution;
  
  if (call_user_plugin) {
    std::abortable_component([&amp;]{ solution = solve(); });
    
    if (!solution)
      call_user_plugin = false;
  }
  
  return solution;
}
</pre>


<h4><a class="sect" id="dis.use.thr">4.1.2. Killing a single thread<span class="link">{dis.use.thr}</span></a></h4>

<p> Suppose that you run a plugin in a separate thread, and in case of failure, you only want to kill that thread.</p>

<pre>
int solve(); <em>// user plugin </em>

int main()
{
  std::optional&lt;int&gt; solution;
  std::jthread t {[&amp;]{
    try {
      std::abortable_component([&amp;]{
        solution = solve();
      });
    }
    catch(...) {
      <em>// swallow</em>
    }
  }};
  
  <em>// main thread ...</em>
}
</pre>


<h4><a class="sect" id="dis.use.utf">4.1.3. Unit-testing preconditions<span class="link">{dis.use.utf}</span></a></h4>


<p> Suppose you want to check, in a program executing unit tests, that function <code>Sqrt</code> has a precondition
    detecting negative inputs. This assumes the program is compiled in <strong>Eval_and_abort</strong> translation
    mode.</p>

<pre>
auto test_precondition_of_sqrt()
{
  bool function_finished = false;
  
  std::abortable_component([&amp;]{
    (void)Sqrt(-1.0);
    function_finished = true;
  });
  
  EXPECT(!function_finished);
}
</pre>


<h4><a class="sect" id="dis.use.res">4.1.4. Resetting the program<span class="link">{dis.use.res}</span></a></h4>

<p> Suppose that after a detected failure, you want to restart the program, but from within the program.</p>

<pre>
int main()
{
  bool finished = false;
 
  std::abortable_component([&amp;]{
    finished = main_program_loop();
  });
	
  while (!finished)
  {
    std::abortable_component([&amp;]{
      necessary_critical_cleanup();
      finished = main_program_loop();
    });
  }
}
</pre>


<h2><a class="sect" id="con">5. Conclusion <span class="link">{con}</span></a></h2>

<p> In this paper we demonstrated that there is at least one way to add support for 
    not-aborting the program upon detecting contract violaiton (while at the same time not letting
    the code dependent on the declared contract execute) after the MVP, while retaining
    backwards compatibiity. "After the MVP" may mean "still in the same release cycle".
    This solution does not require the introduction of a new translation mode.
    Other ways of addressing the same problem, also suitable for a post-MVP addition,
    are also possibe; for instance, the ability to install a custom violation handler
    where throwing an exception is one of the options.
    </p>


<!-- TODO:  ADA -->


<h2><a class="sect" id="ref">7. References <span class="link">{ref}</span></a></h2>


<p> Joshua Berne has reviewed this paper and contributed to its quality.</p>


<h2><a class="sect" id="ref">8. References <span class="link">{ref}</span></a></h2>

<ul>

    <li>[P0542R5] — G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup,
      "Support for contract based programming in C++" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html</a>).
      </li>
      
	<li>[P2388R4] — Andrzej Krzemieński, Gašper Ažman,
      "Minimum Contract Support: either <em>No_eval</em> or <em>Eval_and_abort</em>" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html</a>).
      </li>
	  
  <li>[P2698R0] — Bjarne Stroustrup, "Unconditional termination is a serious problem" <br>
      (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf</a>).
      </li>	


	
</ul>


</body></html>
