Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, is set_terminate local to every thread?

Should set_terminate/get_terminate set a different terminate exception processor for several threads in C++ 2011 or C++ 2003?

E.g. if I have program and sets terminate handler to func_1; then I start 3 threads. What are terminate handlers in new threads? What if in every thread I will set terminate handler to func_2 in first thread, func_3 in second thread and so on.

N3242 (C++ 2011 draft) says nothing about it in [handler.functions] or in [support.exception]/[exception.terminate]

PS: You may answer for C++2011 or for C++2003 of for any popular implementation of these standards

PPS: There is FCD Comment for this... C++ FCD Comment Status Rev. 5 N3249 (2011):

GB 71    18.6.2.4 / 18.8.2.2 / 18.8.3.2   

The thread safety of std::set_new_handler(), std::set_unexpected(), std::set_terminate(), is unspecified making the the functions impossible to use in a thread safe manner.

The thread safety guarantees for the functions must be specified and new interfaces should be provided to make it possible to query and install handlers in a thread safe way.

LWG 1365 ACCEPTED with MODIFICATIONS

See paper N3189

like image 746
osgx Avatar asked Mar 12 '13 16:03

osgx


3 Answers

17.6.4.7p4 says:

Calling the set_* and get_* functions shall not incur a data race. A call to any of the set_* functions shall synchronize with subsequent calls to the same set_* function and to the corresponding get_* function.

This strongly implies that the set_* and get_* functions are operating on the same global state even when called from different threads. All the paragraphs under 18.8.3 discuss "the current handler function", with no other mention of threading; this indicates that the handler function is a property of the program as a whole; similarly, 17.6.4.7 has:

2 - A C++ program may install different handler functions during execution [...]
3 - A C++ program can get a pointer to the current handler function by calling the following functions [...]

These paragraphs discuss the current handler function in the context of a program, indicating that it is program-scope and not thread-local.

like image 77
ecatmur Avatar answered Oct 16 '22 19:10

ecatmur


In the Standard it says under

18.8.3.2 set_terminate [set.terminate]

terminate_handler set_terminate(terminate_handler f) noexcept;

1 Effects: Establishes the function designated by f as the current handler function for terminating exception processing.

[[noreturn]] void terminate() noexcept;

2 Effects: Calls the current terminate_handler function. [ Note: A default terminate_handler is always considered a callable handler in this context. —end note ]

You can see that terminate() calls the current terminate handler, which in the set_handler section it quite clearly says it is used for terminating a process. This gets called when all other exception handling has failed, irrespective from which thread is running.

There is only one terminate handler, and it always gets called from wherever the program is terminating.

like image 4
Tony The Lion Avatar answered Oct 16 '22 19:10

Tony The Lion


The standard doesn't exactly specify; [set.terminate] states only

[...] the current handler function for terminating exception processing.

but doesn't mention if "current" is global or per-thread. So it depends on the implementation.

For example, in MSVC++: https://msdn.microsoft.com/en-us/library/t6fk7h29.aspx

In a multithreaded environment, terminate functions are maintained separately for each thread. Each new thread needs to install its own terminate function. Thus, each thread is in charge of its own termination handling.

like image 4
apenn Avatar answered Oct 16 '22 18:10

apenn