Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit af3a932

Browse files
committed
Gracefully handle assertion errors during runtime startup/teardown
assert() is used throughout the various bits and pieces involved in druntime startup and teardown. However, the default assert handler (throwing an AssertError) requires the GC and exception handling to be up and running, which is not the case for failures e.g. in the module registry code. Of course, these assertions should never be triggered in shipped versions of druntime. But they might be during development, and this change ensures that a sensible error message is printed instead of hitting an infinite recursion or a GC deadlock.
1 parent 3164410 commit af3a932

File tree

3 files changed

+27
-3
lines changed

3 files changed

+27
-3
lines changed

src/core/exception.d

+17-2
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,21 @@ deprecated void setAssertHandler( AssertHandler h ) @trusted nothrow @nogc
416416
assertHandler = h;
417417
}
418418

419+
private __gshared bool assertEHEnabled = false;
420+
extern(C) void _d_setAssertEHEnabled( bool enabled )
421+
{
422+
assertEHEnabled = enabled;
423+
}
424+
425+
private void defaultAssertHandler( string file, size_t line, string msg ) nothrow
426+
{
427+
if ( assertEHEnabled )
428+
throw msg ? new AssertError( msg, file, line ) : new AssertError( file, line );
429+
430+
import core.internal.abort;
431+
abort( file, line, "Assertion failure during runtime startup/teardown",
432+
msg ? ": " : ".", msg );
433+
}
419434

420435
///////////////////////////////////////////////////////////////////////////////
421436
// Overridable Callbacks
@@ -434,7 +449,7 @@ deprecated void setAssertHandler( AssertHandler h ) @trusted nothrow @nogc
434449
extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ ) nothrow
435450
{
436451
if( _assertHandler is null )
437-
throw new AssertError( file, line );
452+
defaultAssertHandler( file, line, null );
438453
_assertHandler( file, line, null);
439454
}
440455

@@ -452,7 +467,7 @@ extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ )
452467
extern (C) void onAssertErrorMsg( string file, size_t line, string msg ) nothrow
453468
{
454469
if( _assertHandler is null )
455-
throw new AssertError( msg, file, line );
470+
defaultAssertHandler( file, line, msg );
456471
_assertHandler( file, line, msg );
457472
}
458473

src/core/internal/abort.d

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ module core.internal.abort;
55
* code, and druntime is -release compiled.
66
*/
77
void abort(string msg, string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
8+
{
9+
abort(filename, line, msg);
10+
}
11+
12+
void abort(string filename, size_t line, const(char)[][] msgs...) @nogc nothrow @safe
813
{
914
import core.stdc.stdlib: c_abort = abort;
1015
// use available OS system calls to print the message to stderr
@@ -40,6 +45,7 @@ void abort(string msg, string filename = __FILE__, size_t line = __LINE__) @nogc
4045
UnsignedStringBuf strbuff;
4146

4247
// write an appropriate message, then abort the program
43-
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff, 10), ") ", msg);
48+
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff, 10), "): ");
49+
writeStr(msgs);
4450
c_abort();
4551
}

src/rt/dmain2.d

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern (C) void rt_moduleTlsDtor();
5050
extern (C) void thread_joinAll();
5151
extern (C) bool runModuleUnitTests();
5252
extern (C) void _d_initMonoTime();
53+
extern (C) void _d_setAssertEHEnabled(bool enabled);
5354

5455
version (OSX)
5556
{
@@ -180,6 +181,7 @@ extern (C) int rt_init()
180181
initStaticDataGC();
181182
lifetime_init();
182183
rt_moduleCtor();
184+
_d_setAssertEHEnabled(true);
183185
rt_moduleTlsCtor();
184186
return 1;
185187
}
@@ -205,6 +207,7 @@ extern (C) int rt_term()
205207
{
206208
rt_moduleTlsDtor();
207209
thread_joinAll();
210+
_d_setAssertEHEnabled(false);
208211
rt_moduleDtor();
209212
gc_term();
210213
finiSections();

0 commit comments

Comments
 (0)