Fix memleak in LogicalState. Ensure processing machinery gets properly shut down on session end.

Clearing the controller field in LogicalState is not enough,
apparently some instances are leaked before the session
gets terminated.
This commit is contained in:
Fedor Isakov 2020-11-27 11:13:38 +01:00
parent 010e6cdc61
commit ac6972106b
4 changed files with 23 additions and 10 deletions

View File

@ -56,6 +56,13 @@ internal class ConstraintsProcessing(
fun getStateCleaner(): ProgramStateCleaner = ProgramStateCleaner()
fun engage(controller: Controller) {
logicalState.setController(controller)
}
fun disengage(controller: Controller) {
logicalState.clearController(controller)
}
fun activateContinue(controller: Controller, activeOcc: Occurrence, parent: MatchJournal.MatchChunk): FeedbackStatus {
assert(activeOcc.stored)

View File

@ -36,6 +36,14 @@ internal class ControllerImpl (
val profiler: Profiler? = null) : Controller, IncrSpecHolder
{
init {
processing.engage(this)
}
fun shutDown() {
processing.disengage(this)
}
/** For tests only */
override fun storeView(): StoreView = processing.storeView()
@ -361,6 +369,5 @@ fun createController(
trace,
profiler
)
logicalState.init(controller)
return controller
}

View File

@ -111,7 +111,6 @@ internal class EvaluationSessionImpl private constructor (
processing.setStrategy(processingStrategy)
val controller = ControllerImpl(supervisor, processing, incrementality, trace, profiler)
logicalState.init(controller)
return SessionParts(program.preambleInfo(), ruleIndex, journal, logicalState, dispatchingFront, controller, processing, processingStrategy)
}
@ -121,18 +120,20 @@ internal class EvaluationSessionImpl private constructor (
journal.view(),
ruleIndex.toRules(),
emptyFrontState(),
logicalState.clear(),
logicalState,
ruleIndex
)
}
override fun runSession(session: SessionParts, main: Constraint): EvaluationResult = with(session) {
val status = run(main)
controller.shutDown()
val newToken = endSession(session)
return EvaluationResultImpl(newToken, status, strategy.invalidatedFeedback())
}
private fun SessionParts.run(main: Constraint): FeedbackStatus = strategy.run(processing, controller, main)
}
open inner class IncrementalProcessingSession(): DefaultProcessingSession() {
@ -151,7 +152,6 @@ internal class EvaluationSessionImpl private constructor (
processing.setStrategy(processingStrategy)
val controller = ControllerImpl(supervisor, processing, incrementality, trace, profiler)
logicalState.init(controller)
return SessionParts(program.preambleInfo(), ruleIndex, journal, logicalState, front, controller, processing, processingStrategy)
}
@ -161,7 +161,7 @@ internal class EvaluationSessionImpl private constructor (
processing.resetStore() // clear observers
// todo: need clearing occurrenceContractObservers? (MPSCR-66)
val principalState = dispatchingFront.sessionState()
return SessionTokenImpl(histView, ruleIndex.toRules(), principalState, logicalState.clear(), ruleIndex)
return SessionTokenImpl(histView, ruleIndex.toRules(), principalState, logicalState, ruleIndex)
}
/**
@ -192,7 +192,6 @@ internal class EvaluationSessionImpl private constructor (
processing.setStrategy(processingStrategy)
val controller = ControllerImpl(supervisor, processing, incrementality, trace, profiler)
logicalState.init(controller)
this.tkn = tkn
return SessionParts(program.preambleInfo(), ruleIndex, journal, logicalState, front, controller, processing, processingStrategy)
@ -214,7 +213,7 @@ internal class EvaluationSessionImpl private constructor (
val rules = ruleIndex.toRules().filter(preambleInfo::inPreamble)
logicalState.reset()
tkn = SessionTokenImpl(histView, rules, principalState, logicalState.clear(), ruleIndex)
tkn = SessionTokenImpl(histView, rules, principalState, logicalState, ruleIndex)
}
return tkn!!
}

View File

@ -50,13 +50,13 @@ class LogicalState : LogicalStateObservable, LogicalObserver
stateFrames.push(LogicalStateFrame())
}
fun init(controller: Controller) {
internal fun setController(controller: Controller) {
assert(this.controller === null)
this.controller = controller
}
fun clear() : LogicalState {
assert(this.controller !== null)
internal fun clearController(currController: Controller) : LogicalState {
assert(this.controller == currController)
this.controller = null
return this
}