@@ -53,7 +53,6 @@ class RunContext(val config: Configuration) {
53
53
var currentThreadId: Long = - 1
54
54
var mainThreadId: Long = - 1
55
55
var bugFound: Throwable ? = null
56
- var mainExiting = false
57
56
var nanoTime = TimeUnit .SECONDS .toNanos(1577768400 )
58
57
val hashCodeMapper = ReferencedContextManager <Int >({ config.randomnessProvider.nextInt() })
59
58
var forkJoinPool: ForkJoinPool ? = null
@@ -187,14 +186,13 @@ class RunContext(val config: Configuration) {
187
186
fun mainExit () {
188
187
val t = Thread .currentThread()
189
188
val context = registeredThreads[t.id]!!
190
- mainExiting = true
191
189
while (registeredThreads.any {
192
190
it.value.state != ThreadState .Completed &&
193
191
it.value.state != ThreadState .Created &&
194
192
it.value != context
195
193
}) {
196
194
try {
197
- context.state = ThreadState .Runnable
195
+ context.state = ThreadState .MainExiting
198
196
scheduleNextOperation(true )
199
197
} catch (e: org.pastalab.fray.runtime.TargetTerminateException ) {
200
198
// If deadlock detected let's try to unblock one thread and continue.
@@ -219,7 +217,6 @@ class RunContext(val config: Configuration) {
219
217
val t = Thread .currentThread()
220
218
step = 0
221
219
bugFound = null
222
- mainExiting = false
223
220
currentThreadId = t.id
224
221
mainThreadId = t.id
225
222
registeredThreads[t.id] = ThreadContext (t, registeredThreads.size, this )
@@ -1014,9 +1011,6 @@ class RunContext(val config: Configuration) {
1014
1011
.toList()
1015
1012
.filter { it.state == ThreadState .Runnable }
1016
1013
.sortedBy { it.thread.id }
1017
- if (mainExiting && (currentThreadId == mainThreadId || enabledOperations.size > 1 )) {
1018
- enabledOperations = enabledOperations.filter { it.thread.id != mainThreadId }
1019
- }
1020
1014
1021
1015
// The first empty check will enable timed operations
1022
1016
if (enabledOperations.isEmpty()) {
@@ -1026,13 +1020,17 @@ class RunContext(val config: Configuration) {
1026
1020
.toList()
1027
1021
.filter { it.state == ThreadState .Runnable }
1028
1022
.sortedBy { it.thread.id }
1029
- if (mainExiting && (currentThreadId == mainThreadId || enabledOperations.size > 1 )) {
1030
- enabledOperations = enabledOperations.filter { it.thread.id != mainThreadId }
1031
- }
1032
1023
}
1033
1024
1034
1025
// The second empty check throws deadlock exceptions.
1035
1026
if (enabledOperations.isEmpty()) {
1027
+ // If no thread is blocked. We are done. Return to main thread and exit.
1028
+ if (registeredThreads.values.none { it.state == ThreadState .Blocked }) {
1029
+ if (currentThreadId != mainThreadId) {
1030
+ registeredThreads[mainThreadId]?.unblock()
1031
+ }
1032
+ return
1033
+ }
1036
1034
val e = DeadlockException ()
1037
1035
reportError(e)
1038
1036
throw e
@@ -1042,7 +1040,7 @@ class RunContext(val config: Configuration) {
1042
1040
if (config.executionInfo.maxScheduledStep in 1 .. < step &&
1043
1041
! currentThread.isExiting &&
1044
1042
Thread .currentThread() !is HelperThread &&
1045
- ! (mainExiting && currentThreadId == mainThreadId) ) {
1043
+ currentThread.state != ThreadState . MainExiting ) {
1046
1044
currentThread.state = ThreadState .Running
1047
1045
val e = LivenessException ()
1048
1046
reportError(e)
0 commit comments