Skip to content

Commit

Permalink
[feenkcom/gtoolkit#3771] Shutdown WeakArray finalization while saving…
Browse files Browse the repository at this point in the history
… an image
  • Loading branch information
akgrant43 committed May 15, 2024
1 parent 587e6f2 commit c0e6efa
Showing 1 changed file with 130 additions and 0 deletions.
130 changes: 130 additions & 0 deletions src/GToolkit-Utility-System/WeakArray.extension.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
Extension { #name : #WeakArray }

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> finalizationProcess [
"The finalization process arranges to send mourn to each element of the VM's finalization queue,
which is accessed via primitiveFetchMourner. The VM signals FinalizationSemaphore whenever
the queue is non-empty. This process loops, waiting on the semaphore, fetches the first element
of the queue and then spawns a process at a higher priority to actually send the mourn messages.
If an error occurs in the higher priority mourn loop process then this process will simply spawn
another process, hence ensuring that errors in finalization methods don't break finalization.
In addition this process also runs the old finalization scheme, supporting clients of the older,
WeakRegistry based scheme. Hopefully this will go away when all clients have moved over."
<gtPharoPatch: #Pharo11>
| throttle firstMourner |
throttle := Semaphore new.
[true] whileTrue: [FinalizationSemaphore wait; initSignals.
"Support the old scheme until things have changed over..."
MournLoopProcess := [firstMourner := self primitiveFetchMourner.
firstMourner notNil] whileTrue:
[[throttle signal.
self mournLoopWith: firstMourner] forkAt: Processor activePriority + 1.
throttle wait]]
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> gtSummaryFor: aView [
<gtView>
<gtClassView>

^ aView columnedList
title: 'Summary';
priority: 10;
items: [ {
'FinalizationProcess' -> (FinalizationProcess isNotNil and: [ FinalizationProcess isTerminated not ]).
'FinalizationSemaphore' -> FinalizationSemaphore size.
'MournLoopProcess' -> (MournLoopProcess isNotNil and: [ MournLoopProcess isTerminated not ]).
'StopRequested' -> StopRequested.
'StoppedSemaphore' -> StoppedSemaphore size. } ];
column: 'Item' text: #key;
column: 'Value' text: #value;
actionUpdateButton.
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> initialize [
"Do we need to initialize specialObjectsArray?"
<gtPharoPatch: #Pharo11>

Smalltalk specialObjectsArray size < 42
ifTrue: [Smalltalk recreateSpecialObjectsArray].

SessionManager default
registerSystemClassNamed: self name.

FinalizationSemaphore := Smalltalk specialObjectsArray at: 42.
StopRequested := false.
StoppedSemaphore := Semaphore new.
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> mournLoopWith: firstMourner [
"Send mourn to all the objects available in the mourn queue, starting
with firstMourner which the sender has already extracted for us. If
an error occurs here, it will break this loop but the sender will spawn
another mournLoopWith: so that finalization is not broken by errors in
individual cases."
<gtPharoPatch: #Pharo11>
| mourner |
mourner := firstMourner.
[ StopRequested ifTrue:
[ StoppedSemaphore signal.
MournLoopProcess := nil.
^ self ].
mourner mourn.
(mourner := self primitiveFetchMourner) notNil] whileTrue.
MournLoopProcess := nil.
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> restartFinalizationProcess [
"kill any old process, just in case"
<gtPharoPatch: #Pharo11>
Stdio stdout
<< 'WeakArray>>restartFinalizationProcess - restarting';
lf.
self stopFinalizationProcess.

FinalizationSemaphore := Smalltalk specialObjectsArray at: 42.
StopRequested := false.
StoppedSemaphore ifNil:
[ StoppedSemaphore := Semaphore new ].
FinalizationProcess := [self finalizationProcess]
forkAt: Processor userInterruptPriority.
FinalizationProcess name: 'WeakArray Finalization Process'
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> shutDown: quitting [
<gtPharoPatch: #Pharo11>

self stopFinalizationProcess
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> startUp: resuming [
<gtPharoPatch: #Pharo11>

self restartFinalizationProcess
]

{ #category : #'*GToolkit-Utility-System' }
WeakArray class >> stopFinalizationProcess [
<gtPharoPatch: #Pharo11>

FinalizationProcess ifNotNil:
[FinalizationProcess terminate.
FinalizationProcess := nil].

MournLoopProcess ifNil: [ ^ self ].
self assert: StoppedSemaphore isSignaled not.
StopRequested := true.
Stdio stdout
<< 'WeakArray>>stopFinalizationProcess - waiting for process shutdown';
lf.
StoppedSemaphore wait.
Stdio stdout
<< 'WeakArray>>stopFinalizationProcess - shutdown complete';
lf.
]

0 comments on commit c0e6efa

Please sign in to comment.