Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory leaks caused by circular referencing. #85

Merged
merged 2 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions core/src/main/kotlin/org/pastalab/fray/core/RunContext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class RunContext(val config: Configuration) {
var bugFound: Throwable? = null
var mainExiting = false
var nanoTime = System.nanoTime()
val terminatingThread = mutableSetOf<Int>()
val hashCodeMapper = ReferencedContextManager<Int>({ config.randomnessProvider.nextInt() })
var forkJoinPool: ForkJoinPool? = null
private val semaphoreManager = ReferencedContextManager {
Expand Down Expand Up @@ -215,7 +214,7 @@ class RunContext(val config: Configuration) {

fun done() {
verifyOrReport(syncManager.synchronizationPoints.isEmpty())
lockManager.done()
lockManager.done(false)
signalManager.done()
stampedLockManager.done()
semaphoreManager.done()
Expand Down Expand Up @@ -1012,7 +1011,7 @@ class RunContext(val config: Configuration) {
}

fun nanoTime(): Long {
nanoTime += TimeUnit.MILLISECONDS.convert(100, TimeUnit.NANOSECONDS)
nanoTime += TimeUnit.MILLISECONDS.convert(10000, TimeUnit.NANOSECONDS)
return nanoTime
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,7 @@ class RuntimeDelegate(val context: RunContext) : org.pastalab.fray.runtime.Deleg
}

override fun onReentrantReadWriteLockInit(lock: ReentrantReadWriteLock) {
if (checkEntered()) return
context.reentrantReadWriteLockInit(lock.readLock(), lock.writeLock())
entered.set(false)
}

override fun onSemaphoreInit(sem: Semaphore) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import java.nio.file.Paths
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.createDirectories
import kotlin.io.path.deleteRecursively
import kotlin.io.path.exists
import kotlin.time.TimeSource
import kotlinx.serialization.Polymorphic
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -247,7 +248,7 @@ data class Configuration(
val frayLogger = FrayLogger("$report/fray.log")

init {
if (!isReplay) {
if (!isReplay || !Paths.get(report).exists()) {
prepareReportPath(report)
}
if (System.getProperty("fray.recordSchedule", "false").toBoolean()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
package org.pastalab.fray.core.concurrency.primitives

import java.lang.ref.WeakReference
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.Lock
import org.pastalab.fray.core.ThreadContext
import org.pastalab.fray.core.concurrency.operations.ConditionAwaitBlocked
import org.pastalab.fray.core.concurrency.operations.ConditionWakeBlocked
import org.pastalab.fray.rmi.ThreadState

class ConditionSignalContext(lockContext: LockContext, val lock: Lock, val condition: Condition) :
class ConditionSignalContext(lockContext: LockContext, lock: Lock, val condition: Condition) :
SignalContext(lockContext) {
val lockReference = WeakReference(lock)

override fun sendSignalToObject() {
lock.lock()
lockReference.get()?.lock()
try {
condition.signalAll()
} finally {
lock.unlock()
lockReference.get()?.unlock()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.pastalab.fray.core.concurrency.primitives

import java.lang.ref.WeakReference
import java.util.concurrent.CountDownLatch
import org.pastalab.fray.core.ThreadContext
import org.pastalab.fray.core.concurrency.SynchronizationManager
Expand All @@ -12,10 +13,11 @@ import org.pastalab.fray.rmi.ThreadState
* Context for a [CountDownLatch]. We have to pass syncManager here because we need to create a
* synchronization point when we unblock a thread forcefully.
*/
class CountDownLatchContext(val latch: CountDownLatch, val syncManager: SynchronizationManager) :
class CountDownLatchContext(latch: CountDownLatch, val syncManager: SynchronizationManager) :
InterruptibleContext {
var count = latch.count
val latchWaiters = mutableMapOf<Long, LockWaiter>()
val latchReference = WeakReference(latch)

fun await(canInterrupt: Boolean, thread: ThreadContext): Boolean {
if (count > 0) {
Expand Down Expand Up @@ -59,12 +61,14 @@ class CountDownLatchContext(val latch: CountDownLatch, val syncManager: Synchron
if (type == InterruptionType.FORCE) {
while (count != 0L) {
val unblockedThreads = countDown()
if (unblockedThreads > 0) {
syncManager.createWait(latch, unblockedThreads)
latch.countDown()
syncManager.wait(latch)
} else {
latch.countDown()
latchReference.get()?.let { latch ->
if (unblockedThreads > 0) {
syncManager.createWait(latch, unblockedThreads)
latch.countDown()
syncManager.wait(latch)
} else {
latch.countDown()
}
}
}
return false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package org.pastalab.fray.core.concurrency.primitives

import java.lang.ref.WeakReference
import org.pastalab.fray.core.ThreadContext
import org.pastalab.fray.core.concurrency.operations.ObjectWaitBlock
import org.pastalab.fray.core.concurrency.operations.ObjectWakeBlocked
import org.pastalab.fray.rmi.ThreadState

class ObjectNotifyContext(lockContext: LockContext, val obj: Any) : SignalContext(lockContext) {
class ObjectNotifyContext(lockContext: LockContext, obj: Any) : SignalContext(lockContext) {
val objReference = WeakReference(obj)

override fun sendSignalToObject() {
synchronized(obj) { (obj as Object).notifyAll() }
objReference.get()?.let { obj -> synchronized(obj) { (obj as Object).notifyAll() } }
}

override fun updatedThreadContextDueToUnblock(
Expand Down
Loading