Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing a C++ exception inside an omp critical section

Tags:

c++

openmp

I'm wondering if it is safe to throw an C++ exception inside an OMP critical section.

#pragma omp critical (my_critical_section)
{
    ...
    throw my_exception("failed")
    ...       
}

g++ does not complain. I'm puzzled because it complains about return statements inside the critical section. It returns the error: invalid exit from OpenMP structured block when I write

#pragma omp critical (my_critical_section)
{
    ...
    return;
    ...       
}

So, why is it OK to leave the critical section with an exception, but it is not OK to leave it with a return statement?

like image 482
Leonardo de Moura Avatar asked Dec 01 '12 20:12

Leonardo de Moura


People also ask

What does OMP critical do?

Purpose. The omp critical directive identifies a section of code that must be executed by a single thread at a time.

What is critical section OpenMP?

Use OpenMP critical sections to prevent multiple threads from accessing the critical section's code at the same time, thus only one active thread can update the data referenced by the code. Critical sections are useful for a non-nested mutex.

What is a critical compiler directive in OpenMP?

Specifies that only the main thread should execute a section of the program. critical. Specifies that code is only executed on one thread at a time. barrier. Synchronizes all threads in a team; all threads pause at the barrier, until all threads execute the barrier.


1 Answers

No, it is not OK to leave a critical section with exceptions. g++ does not complain in this case but it silently inserts an implicit try/catch around the block of the critical section. For example the following code:

#pragma omp critical (my_crit)
{
   throw 3;
}

gets lowered by the OpenMP processor of GCC 4.7 into:

#pragma omp critical (my_crit)
__builtin_GOMP_critical_name_start (&.gomp_critical_user_my_crit);
try
  {
    D.20639 = __cxa_allocate_exception (4);
    try
      {
        MEM[(int *)D.20639] = 3;
      }
    catch
      {
        __cxa_free_exception (D.20639);
      }
    __cxa_throw (D.20639, &_ZTIi, 0B);
  }
catch
  {
    <<<eh_must_not_throw (terminate)>>>
  }
__builtin_GOMP_critical_name_end (&.gomp_critical_user_my_crit);

Reaching the implicit built-in catch-all handler <<<eh_must_not_throw (terminate)>>> results in quite ungraceful termination:

terminate called after throwing an instance of 'int'
Abort trap: 6

The implicit try/catch is inserted regardless of the presence of an outer try/catch construct, i.e. the exception would never ever leave the critical section.

The OpenMP standard mandates, that if an exception is thrown within most OpenMP constructs (parallel, section, master, single, for, critical, task, etc.), execution must resume within the same construct and that the same thread must catch the exception. Violation of this restriction leads to non-conformant OpenMP code and g++ simply enforces the conformance by inserting try/catch blocks with termination handlers inside all such constructs.

As for the error when a return statement is present, OpenMP defines a strcutured block in C/C++ as:

For C/C++, an executable statement, possibly compound, with a single entry at the top and a single exit at the bottom, or an OpenMP construct.

and also (for all languages):

The point of exit cannot be a branch out of the structured block.

Obviously return constitutes a branch ouf of the block, different from simply falling of the bottom of the block.

like image 112
Hristo Iliev Avatar answered Nov 16 '22 03:11

Hristo Iliev