@@ -605,22 +605,38 @@ void my_assertHandlerLongJmp(const char *, // text
605
605
longjmp (my_setJmpBuf, true );
606
606
}
607
607
608
- void my_failureHandlerLongJmp ()
609
- {
608
+ struct my_FailureHandlerLongJmp {
609
+ // The Solaris GNU compiler, when optimized in C++11 or beyond, somehow
610
+ // corrupts memory if 'longjmp' is called from a d'tor. For reasons I
611
+ // don't understand, the problem goes away if this handler is a functor and
612
+ // not a free function.
613
+ //
614
+ // It was very hard to narrow down, but if the handler is a free function
615
+ // in a 'bsl::function<void()>', it somehow corrupts the 'bsl::function'
616
+ // object such that the next assignment to that 'bsl::function' object
617
+ // results in either a segfault or an illegal instruction. The problem
618
+ // mysteriously comes and goes as debug traces are added and removed. If
619
+ // the 'bsl::function' contains a functor and not a ptr to a free function,
620
+ // the problem somehow doesn't happen.
621
+
622
+ void operator ()() {
610
623
#ifdef BSLS_PLATFORM_OS_WINDOWS
611
- // setjmp / longjmp is flaky on Windows
624
+ // setjmp / longjmp is flaky on Windows
612
625
613
- ASSERT (0 );
626
+ ASSERT (0 );
614
627
#endif
615
628
616
- longjmp (my_setJmpBuf, true );
617
- }
629
+ longjmp (my_setJmpBuf, true );
630
+ }
631
+ };
618
632
619
633
bool my_failureHandlerFlag = false ;
620
- void my_failureHandlerSetFlag ()
621
- {
622
- my_failureHandlerFlag = true ;
623
- }
634
+ struct my_FailureHandlerSetFlag {
635
+ void operator ()()
636
+ {
637
+ my_failureHandlerFlag = true ;
638
+ }
639
+ };
624
640
625
641
#ifdef BSLS_PLATFORM_OS_WINDOWS
626
642
enum { ABORT_LIMIT = 1 };
@@ -1966,9 +1982,14 @@ int main(int argc, char *argv[])
1966
1982
ASSERT (ABORT);
1967
1983
}
1968
1984
else {
1969
- ta.setFailureHandler (ABORT
1970
- ? &my_failureHandlerLongJmp
1971
- : &my_failureHandlerSetFlag);
1985
+ if (ABORT) {
1986
+ ta.setFailureHandler (
1987
+ my_FailureHandlerLongJmp ());
1988
+ }
1989
+ else {
1990
+ ta.setFailureHandler (
1991
+ my_FailureHandlerSetFlag ());
1992
+ }
1972
1993
my_failureHandlerFlag = false ;
1973
1994
1974
1995
ta.deallocate (ptr);
@@ -2029,9 +2050,14 @@ int main(int argc, char *argv[])
2029
2050
ASSERT (ABORT);
2030
2051
}
2031
2052
else {
2032
- ta.setFailureHandler (ABORT
2033
- ? &my_failureHandlerLongJmp
2034
- : &my_failureHandlerSetFlag);
2053
+ if (ABORT) {
2054
+ ta.setFailureHandler (
2055
+ my_FailureHandlerLongJmp ());
2056
+ }
2057
+ else {
2058
+ ta.setFailureHandler (
2059
+ my_FailureHandlerSetFlag ());
2060
+ }
2035
2061
2036
2062
my_failureHandlerFlag = false ;
2037
2063
@@ -2161,8 +2187,14 @@ int main(int argc, char *argv[])
2161
2187
ASSERT (ABORT);
2162
2188
}
2163
2189
else {
2164
- tba.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2165
- : &my_failureHandlerSetFlag);
2190
+ if (ABORT) {
2191
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2192
+ tba.setFailureHandler (my_FailureHandlerLongJmp ());
2193
+ }
2194
+ else {
2195
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2196
+ tba.setFailureHandler (my_FailureHandlerSetFlag ());
2197
+ }
2166
2198
2167
2199
void *ptr = tba.allocate (6 );
2168
2200
@@ -2209,8 +2241,12 @@ int main(int argc, char *argv[])
2209
2241
ASSERT (ABORT);
2210
2242
}
2211
2243
else {
2212
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2213
- : &my_failureHandlerSetFlag);
2244
+ if (ABORT) {
2245
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2246
+ }
2247
+ else {
2248
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2249
+ }
2214
2250
2215
2251
ASSERT (oss. str ().empty ());
2216
2252
ASSERT (oss2.str ().empty ());
@@ -2263,8 +2299,12 @@ int main(int argc, char *argv[])
2263
2299
ASSERT (ABORT);
2264
2300
}
2265
2301
else {
2266
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2267
- : &my_failureHandlerSetFlag);
2302
+ if (ABORT) {
2303
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2304
+ }
2305
+ else {
2306
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2307
+ }
2268
2308
2269
2309
ASSERT (oss.str ().empty ());
2270
2310
@@ -2307,8 +2347,12 @@ int main(int argc, char *argv[])
2307
2347
ASSERT (ABORT);
2308
2348
}
2309
2349
else {
2310
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2311
- : &my_failureHandlerSetFlag);
2350
+ if (ABORT) {
2351
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2352
+ }
2353
+ else {
2354
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2355
+ }
2312
2356
2313
2357
ASSERT (oss.str ().empty ());
2314
2358
@@ -2351,8 +2395,12 @@ int main(int argc, char *argv[])
2351
2395
ASSERT (ABORT);
2352
2396
}
2353
2397
else {
2354
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2355
- : &my_failureHandlerSetFlag);
2398
+ if (ABORT) {
2399
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2400
+ }
2401
+ else {
2402
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2403
+ }
2356
2404
2357
2405
ASSERT (oss.str ().empty ());
2358
2406
@@ -2397,8 +2445,12 @@ int main(int argc, char *argv[])
2397
2445
ASSERT (ABORT);
2398
2446
}
2399
2447
else {
2400
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2401
- : &my_failureHandlerSetFlag);
2448
+ if (ABORT) {
2449
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2450
+ }
2451
+ else {
2452
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2453
+ }
2402
2454
2403
2455
ASSERT (oss.str ().empty ());
2404
2456
@@ -2443,8 +2495,12 @@ int main(int argc, char *argv[])
2443
2495
ASSERT (ABORT);
2444
2496
}
2445
2497
else {
2446
- ta.setFailureHandler (ABORT ? &my_failureHandlerLongJmp
2447
- : &my_failureHandlerSetFlag);
2498
+ if (ABORT) {
2499
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2500
+ }
2501
+ else {
2502
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2503
+ }
2448
2504
2449
2505
ASSERT (oss.str ().empty ());
2450
2506
@@ -2493,8 +2549,12 @@ int main(int argc, char *argv[])
2493
2549
ASSERT (ABORT);
2494
2550
}
2495
2551
else {
2496
- ta.setFailureHandler (ABORT ?&my_failureHandlerLongJmp
2497
- :&my_failureHandlerSetFlag);
2552
+ if (ABORT) {
2553
+ ta.setFailureHandler (my_FailureHandlerLongJmp ());
2554
+ }
2555
+ else {
2556
+ ta.setFailureHandler (my_FailureHandlerSetFlag ());
2557
+ }
2498
2558
2499
2559
ASSERT (oss.str ().empty ());
2500
2560
@@ -2657,15 +2717,6 @@ int main(int argc, char *argv[])
2657
2717
#ifdef BSLS_PLATFORM_OS_WINDOWS
2658
2718
break ;
2659
2719
#endif
2660
- #if defined(BSLS_PLATFORM_OS_SOLARIS) && defined(BSLS_PLATFORM_CMP_GNU) && \
2661
- defined (BDE_BUILD_TARGET_OPT)
2662
- // There seems to be a compiler bug in Solaris GNU compilers where,
2663
- // with the optimizer on, the `longjmp` here corrupts a nearby
2664
- // automatic variable. Let's face it -- doing a `longjmp` out of a
2665
- // d'tor is not a very important test.
2666
-
2667
- break ;
2668
- #endif
2669
2720
2670
2721
if (verbose) Q (Longjmp on destruction with blocks outstanding);
2671
2722
{
@@ -2710,7 +2761,7 @@ int main(int argc, char *argv[])
2710
2761
ASSERT (pta->numBlocksInUse () == numAllocs);
2711
2762
}
2712
2763
else {
2713
- pta->setFailureHandler (&my_failureHandlerLongJmp );
2764
+ pta->setFailureHandler (my_FailureHandlerLongJmp () );
2714
2765
2715
2766
if (veryVerbose) P (staBlocks);
2716
2767
@@ -3378,10 +3429,10 @@ int main(int argc, char *argv[])
3378
3429
}
3379
3430
else {
3380
3431
if (FAILURE_LONGJMP) {
3381
- ta.setFailureHandler (&my_failureHandlerLongJmp );
3432
+ ta.setFailureHandler (my_FailureHandlerLongJmp () );
3382
3433
}
3383
3434
else {
3384
- ta.setFailureHandler (&my_failureHandlerSetFlag );
3435
+ ta.setFailureHandler (my_FailureHandlerSetFlag () );
3385
3436
}
3386
3437
3387
3438
my_failureHandlerFlag = false ;
0 commit comments