Skip to content

Commit 9a03d19

Browse files
committed
Fix for logic to handle termination of process which waits for the lock
1 parent 04f16d4 commit 9a03d19

5 files changed

Lines changed: 17 additions & 12 deletions

File tree

ReadWriteLock-Tests.package/ReadWriteLockTests.class/instance/testTerminatingReadWhichWaitingWriteAndAnotherRead.st

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ testTerminatingReadWhichWaitingWriteAndAnotherRead
1818
self passForkedProcesses.
1919
lastReaderExecuted should be: false.
2020
secondReader terminate.
21+
22+
self passForkedProcesses. "Now last read should be still locked"
23+
lastReaderExecuted should be: false.
2124
writeSemaphore signal.
2225
self waitForkedProcesses.
2326
lastReaderExecuted should be: true.

ReadWriteLock.package/PrimitiveLock.class/instance/handleProcessTerminationOfWaitingContext..st

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,15 @@ This method called from Process>>terminate when it detects waiting me. My users
77
ensure: [ releaseNotRequired ifFalse: [ lock release ] ]
88
This code is not working correctly by itself. When current process waits on 'lock acquire' somebody can terminate it and ensure will release me which shoud not happens in this case. But if I was acquired but process is just suspended on 'lock acquire' then process termination should execute ensure block to release me.
99
This problem solved by this special method. Process>>terminate detects first case and inject right value for tracking variable. Senders should mark method with special pragma
10-
<lockAt: #lockVariableName tracksStateAt: 1> 'index of local variable'
11-
Method can contain mulpible pragmas for referenced locks. (ReadWriteLock for example needs this).
12-
"
13-
| receiver lockFlagIndex |
10+
<lockAt: #lockVariableName tracksStateAt: #tempName> 'var name which keeps the lock state'
11+
Method can contain multiple pragmas for referenced locks. (ReadWriteLock for example needs this)"
12+
| receiver |
1413
receiver := suspendedContext receiver.
1514

16-
suspendedContext method pragmas do: [ :pragma |
17-
15+
suspendedContext method pragmas do: [ :pragma |
1816
pragma keyword == #lockAt:tracksStateAt: ifTrue: [
1917
(receiver readSlotNamed: pragma arguments first) == self ifTrue: [
20-
lockFlagIndex := pragma arguments last.
21-
suspendedContext home namedTempAt: lockFlagIndex put: true
18+
self resetLockFlag: pragma arguments last in: suspendedContext home.
2219
]
2320
]
2421
].
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
process termination handling
2+
resetLockFlag: flagTempName in: criticalContext
3+
4+
criticalContext debuggerMap tempNamed: flagTempName in: criticalContext put: true

ReadWriteLock.package/ReadWriteLock.class/instance/criticalRead..st

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ criticalRead: aBlock
77
Given block is safe for recursive read/write sections
88
"
99
| readLockAcquiredNotHere newReadersCount writeLockAcquiredNotHere readingPrepared writeLockWasAsked |
10-
<lockAt: #readLock tracksStateAt: 1>
11-
<lockAt: #writeLock tracksStateAt: 3>
10+
<lockAt: #readLock tracksStateAt: #readLockAcquiredNotHere>
11+
<lockAt: #writeLock tracksStateAt: #writeLockAcquiredNotHere>
1212

1313
readLockAcquiredNotHere := true.
1414
writeLockAcquiredNotHere := true.
@@ -26,9 +26,10 @@ criticalRead: aBlock
2626
readingPrepared := true.
2727
readLockAcquiredNotHere := true.
2828
readLock release] ifCurtailed: [
29+
2930
newReadersCount ifNotNil: [ currentReaders := newReadersCount - 1 ]. "we should restore previous value because we can't prepare reading (process was terminated)"
3031
readLockAcquiredNotHere ifFalse: [readLock release].
31-
writeLockAcquiredNotHere ifFalse: [ writeLock release]].
32+
writeLockAcquiredNotHere ifFalse: [writeLock release]].
3233
^aBlock value] ensure: [
3334
readingPrepared ifTrue: [
3435
readLock acquire.

ReadWriteLock.package/ReadWriteLock.class/instance/criticalWrite..st

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ criticalWrite: aBlock
77
Given block is safe for recursive read/write sections
88
"
99
| lockAcquiredNotHere |
10-
<lockAt: #writeLock tracksStateAt: 1>
10+
<lockAt: #writeLock tracksStateAt: #lockAcquiredNotHere>
1111

1212
lockAcquiredNotHere := true.
1313

0 commit comments

Comments
 (0)