Bug 18504 – Assert in synchronized crashes with SIGILL on exit
Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2018-02-23T12:53:02Z
Last change time
2018-04-02T11:27:23Z
Assigned to
No Owner
Creator
FeepingCreature
Comments
Comment #0 by default_357-line — 2018-02-23T12:53:02Z
Testcase:
void main() { synchronized assert(0); }
Expected: Error printed, program exits with error code.
Actual: Error printed, program exits with Illegal Instruction.
What happens:
In 9327d158d457093f5fc064a844f3400515558112 (emit better code for try-finally when function does not throw) for v2.078.0, Walter added an optimization that finally blocks can be handled more efficiently if the function does not throw exceptions.
AssertError is not an exception.
As a result, the mutex of the synchronized{} block is never unlocked.
On program exit, the runtime tries to clean up mutexes at program end. (_d_critical_term -> destroyMutex -> pthread_mutex_destroy)
pthread_mutex_destroy errors if the mutex is still locked. This triggers the assert(0), which shows (in release mode) as a ud2: illegal instruction.
Comment #1 by default_357-line — 2018-02-23T12:55:36Z
Note that this issue appears in a similar form with crashes on GC cleanup of objects if an assert failed in a synchronized(this) invariant block.