Skip to content

Commit 24474a2

Browse files
committed
Monitor>>critical: handle the case where the requestingProcess gets the signal, but the ownerProcess isn't yet set.
fix: #18104
1 parent 242bbac commit 24474a2

File tree

1 file changed

+16
-17
lines changed

1 file changed

+16
-17
lines changed

src/Kernel/Monitor.class.st

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -107,35 +107,34 @@ Monitor >> critical: aBlock [
107107
in a critical section.
108108
NOTE: All the following synchronization operations are only valid inside the critical section
109109
of the monitor!"
110-
| requestingProcess blockValue caught |
110+
| requestingProcess caught |
111111

112112
requestingProcess := Processor activeProcess.
113113
caught := false.
114-
[
115-
"See Semaphore>>critical: for a description of the structure of the code below."
114+
^ [ "See Semaphore>>critical: for a description of the structure of the code below."
116115
requestingProcess == ownerProcess ifTrue: [
117116
"Don't move the caught assignment outside the ifTrue:ifFalse, see below"
118117
caught := true.
119118
nestingLevel := nestingLevel + 1.
120119
] ifFalse: [
121-
"Set caught immediately before the mutex wait to ensure the process isn't interrupted"
120+
"Only one process should be able to enter the critical: section at a time,
121+
however there is obviously a window where terminating a process can allow two
122+
processes in at the same time.
123+
Protect against this by rewaiting if someone else owns the monitor."
124+
[ "Set caught immediately before the mutex wait to ensure both are executed as an atomic operation"
122125
caught := true.
123-
mutex wait.
126+
mutex wait] doWhileFalse: [ ownerProcess isNil ].
124127
ownerProcess := requestingProcess.
125-
nestingLevel := 1.
126-
].
127-
128-
"The critical section is only exited if:
129-
1. the ensured block was entered (caught), and
130-
2. the process exiting was the owning process
131-
If the process being terminted was waiting on the monitor and there is no
132-
current owner, the mutex needs to be signalled to reestablish the excess signal."
133-
blockValue := aBlock value ] ensure:
128+
nestingLevel := 1. ].
129+
aBlock value ] ensure:
130+
"The critical section is only exited if:
131+
1. the ensured block was entered (caught), and
132+
2. the process exiting was the owning process
133+
If the process being terminted was waiting on the monitor (caught) and there is no
134+
current owner, the mutex needs to be signalled to reestablish the excess signal."
134135
[ caught ifTrue: [ requestingProcess == ownerProcess
135136
ifTrue: [ self exit ]
136-
ifFalse: [ (ownerProcess == nil and: [ nestingLevel = 0 ])
137-
ifTrue: [ mutex signal ] ] ] ].
138-
^ blockValue
137+
ifFalse: [ ownerProcess ifNil: [ mutex signal ] ] ] ].
139138
]
140139

141140
{ #category : 'private' }

0 commit comments

Comments
 (0)