IBM Support

Issues with mixing setjmp()/longjmp() with C++ exceptions

Troubleshooting


Problem

C++ exception handling does not behave as intended when mixing it with setjmp()/longjmp() functions.

Symptom

Programs that depend on C++ exceptions being automatically cleaned up may be affected by mixing setjmp()/longjmp() functions with C++ exceptions.

Consider the problematic test case below:


$cat test.cpp
#include <iostream>
#include <setjmp.h>

using namespace std;

main()
{
  jmp_buf state;
  int value = 0;
  int count = 0;

  value=setjmp(state);

  printf ("val is %d\n",value);
 
  ++count;

  try
  {
  if (count == 1)
  throw 1;
  }
  catch (...)
  {
    printf ("In catch before longjmp\n");
    longjmp(state, 1);
    printf ("In catch after longjmp\n");
  }

  printf ("After try catch\n");
 
  return 0;
}
$

Cause

The C++ standard mentions that the interaction between setjmp()/longjmp() with C++ exceptions (and normal end of scope clean up) is undefined.

On AIX, calling longjmp() from inside the catch block will bypass all destructor calls at the end of a scope and the clean up of the C++ exception.

Environment

AIX

Diagnosing The Problem

The problem can be diagnosed by using the profiled C++ Runtime where you can analyze the ehlogs and see the missing destructors calls and C++ exception clean up functions.

Example of missing cleaup functions for test.cpp from above:



$ cat ehlog43188270-f066cbd4-1.log
0:74187005:v6:
1:74187005:v6:DOTHROW: ----------------------------starting exception processing-----------------------------
2:74187005:v6:Throwing exception, name:(i:0), sp(0x2ff229e0)
3:74187005:v6:pc(0x1000072c), nested(no),
.
.
.28:74187005:v6:..leaving DoThrow for a catch block
29:74187005:v6:DOTHROW: ----------------------------ending exception processing-----------------------------
.
.
//Normally, there would be a CLEANUP section here
$

Resolving The Problem

The problem can be resolved by avoiding setjmp()/longjmp() functions within the 'try-catch' blocks.

One solution would be to detect, via a 'flag' variable, that an exception was caught; and then using the longjmp() function call outside of the try-catch block depending on the value of the 'flag' variable.

Example:

$

.


catch
{
    flag = 1;
}

if (flag == 1) longjmp(state, 1);
.
$

By bringing out the longjmp() from the try-cath block, you will notice that the ehlogs will now contain the CLEANUP sections:

$cat ehlog43188270-f066cbd4-1.log

.

.


32:69009571:v6:CLEANUP: ----------------------------starting exception cleaning-----------------------------
33:69009571:v6:Cleaning up Exception, catch_state(1), cleanup ctr(1)
34:69009571:v6:---- Exception Chain Empty ----
.
.
$

[{"Product":{"code":"SSGH3R","label":"XL C\/C++ for AIX"},"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Component":"Compiler","Platform":[{"code":"PF002","label":"AIX"}],"Version":"11.1;12.1;13.1;13.1.2;13.1.3","Edition":"","Line of Business":{"code":"LOB57","label":"Power"}}]

Document Information

Modified date:
06 December 2018

UID

swg21590839