@@ -174,7 +174,7 @@ void libmesh_handleSEGV(int /*signo*/, siginfo_t * info, void * /*context*/)
174174 << " bt" );
175175}
176176#endif
177- }
177+ } // anonymous namespace
178178
179179
180180
@@ -278,6 +278,36 @@ void uninstall_thread_buffered_sync()
278278 }
279279}
280280
281+
282+ /**
283+ * Helper to do cleanup from both destructor and terminate
284+ */
285+ void cleanup_stream_buffers ()
286+ {
287+ // Before resetting the stream buffers, let's remove our thread wrappers
288+ if (!libMesh ::on_command_line ("--disable-thread-safe-output" ))
289+ uninstall_thread_buffered_sync ();
290+
291+ if (libMesh ::on_command_line ("--redirect-stdout" ) ||
292+ libMesh ::on_command_line ("--redirect-output" ))
293+ {
294+ // If stdout/stderr were redirected to files, reset them now.
295+ libMesh ::out .rdbuf (out_buf );
296+ libMesh ::err .rdbuf (err_buf );
297+ }
298+
299+ // If we built our own output streams, we want to clean them up.
300+ if (libMesh ::on_command_line ("--separate-libmeshout" ))
301+ {
302+ delete libMesh ::out .get ();
303+ delete libMesh ::err .get ();
304+
305+ libMesh ::out .reset (std ::cout );
306+ libMesh ::err .reset (std ::cerr );
307+ }
308+ }
309+
310+
281311bool warned_about_auto_ptr (false );
282312
283313PerfLog perflog ("libMesh" ,
@@ -401,6 +431,11 @@ void libmesh_terminate_handler()
401431 libMesh ::perflog .print_log ();
402432 libMesh ::perflog .clear ();
403433
434+ // Now that we're done with output we should clean up our stream
435+ // buffers; if we fail to uninstall_thread_buffered_sync() when
436+ // needed we can end up seeing a segfault in iostreams destructors
437+ cleanup_stream_buffers ();
438+
404439 // If we have MPI and it has been initialized, we need to be sure
405440 // and call MPI_Abort instead of std::abort, so that the parallel
406441 // job can die nicely.
@@ -794,14 +829,21 @@ LibMeshInit::LibMeshInit (int argc, const char * const * argv,
794829LibMeshInit ::~LibMeshInit ()
795830{
796831 // Every processor had better be ready to exit at the same time.
797- // This would be a libmesh_parallel_only() function, except that
798- // libmesh_parallel_only() uses libmesh_assert() which throws an
799- // exception() which causes compilers to scream about exceptions
800- // inside destructors.
801-
802832 // Even if we're not doing parallel_only debugging, we don't want
803833 // one processor to try to exit until all others are done working.
804- this -> comm ().barrier ();
834+
835+ // We could be destructing here because we're unwinding the stack
836+ // due to a thrown exception, though. It's possible that an
837+ // application is catching exceptions outside of the LibMeshInit
838+ // scope, or that we're using a C++ compiler that does unwinding
839+ // for uncaught exceptions (the standard says whether to go straight
840+ // to terminate() or unwind first is "implementation-defined"). If
841+ // *that* is the case then we can't safely communicate with other
842+ // processors that might not all be unwinding too.
843+ #ifdef LIBMESH_ENABLE_EXCEPTIONS
844+ if (!std ::uncaught_exceptions ())
845+ #endif
846+ this -> comm ().barrier ();
805847
806848 // We can't delete, finalize, etc. more than once without
807849 // reinitializing in between
@@ -854,27 +896,7 @@ LibMeshInit::~LibMeshInit()
854896 // Set the initialized() flag to false
855897 libMeshPrivateData ::_is_initialized = false;
856898
857- // Before resetting the stream buffers, let's remove our thread wrappers
858- if (!libMesh ::on_command_line ("--disable-thread-safe-output" ))
859- uninstall_thread_buffered_sync ();
860-
861- if (libMesh ::on_command_line ("--redirect-stdout" ) ||
862- libMesh ::on_command_line ("--redirect-output" ))
863- {
864- // If stdout/stderr were redirected to files, reset them now.
865- libMesh ::out .rdbuf (out_buf );
866- libMesh ::err .rdbuf (err_buf );
867- }
868-
869- // If we built our own output streams, we want to clean them up.
870- if (libMesh ::on_command_line ("--separate-libmeshout" ))
871- {
872- delete libMesh ::out .get ();
873- delete libMesh ::err .get ();
874-
875- libMesh ::out .reset (std ::cout );
876- libMesh ::err .reset (std ::cerr );
877- }
899+ cleanup_stream_buffers ();
878900
879901#ifdef LIBMESH_ENABLE_EXCEPTIONS
880902 // Reset the old terminate handler; maybe the user code wants to
0 commit comments