Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must user provided terminate() function be thread-safe?

As stated in http://en.cppreference.com/w/cpp/error/terminate there are many reasons to call terminate. I can imagine case where just almost in the same time some of these reasons happen in two threads.

Q1 Can the terminate function set by std::set_terminate be called twice or more at the same time, by the same time I mean second call begins before first has ended.

  Thread1   Thread2
    |          |
    _          |
    t          |
    e          |
    r          |
    m          |
    i          _
    n          t
    a          e
    t          r
    e          m
    -          ?

Q2 If Q1==YES, then what happens if first terminate ended. I guess if it ended with std::abort, then program ends, but what happens if user provided terminate does not abort program?

Q3 Is the terminate function set by std::set_terminate called in context of the thread which caused this terminate call?

like image 825
PiotrNycz Avatar asked Oct 27 '12 20:10

PiotrNycz


People also ask

Is functions thread-safe?

Thread safety A threadsafe function protects shared resources from concurrent access by locks. Thread safety concerns only the implementation of a function and does not affect its external interface. The use of global data is thread-unsafe.

How do you make a function thread-safe?

This can be fixed by adding a mutex that demands that two threads cannot run the run member simultaneously. See Boost. Thread for a good mutex example. Please include an example to clarify that a const (read-only) function also needs mutex protection if another function may write to the data member at the same time.


Video Answer


1 Answers

Q1

Yes, std::terminate can be called concurrently.

Q2

The standard says it is undefined behavior for a terminate_handler to not "terminate execution of the program without returning to the caller". In implementations I'm familiar with, if the terminate_handler attempts to return, either normally, or exceptionally, abort() will be called.

Q3

The function set by std::terminate is a global, not a thread local. So one thread can impact another.

In C++98/03, the terminate_handler used when terminate is called due to an uncaught exception is the one that was in effect when the exception was thrown, not the one in effect when terminate is actually called (though they are usually the same).

In C++11 this was changed and the standard now says that the handler used is the one in place at the time terminate is called. This change was done by mistake and will most likely be corrected in a future draft. Here is the LWG issue tracking this issue:

http://cplusplus.github.com/LWG/lwg-active.html#2111

Update

At the Spring 2015 meeting in Lenexa, KS, the LWG decided to standardize existing behavior and made it unspecified when a new terminate_handler goes into effect if set_terminate is called during stack unwinding. I.e. implementations are allowed to follow either the C++98/03 rules or the C++11 rules.

To make your code portable, if you need to set a terminate_handler, do so during program startup, before any exceptions will be thrown, and do not make a habit of calling set_terminate after that.

like image 170
Howard Hinnant Avatar answered Oct 16 '22 01:10

Howard Hinnant