[Bug?] Global EventTable, debugger and deadlocks

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[Bug?] Global EventTable, debugger and deadlocks

Holger Kleinsorgen-4
Hi,

while debugging some code I repeatedly encountered a deadlock situation
caused by the global EventTable dictionary and its lock.
While interrupting a process that was about to grow a collection and
entered the lock along the way, the debugger also wanted to enter the
lock, causing a deadlock.

process 0x8464084 priority: 90

frame 0xbfa5aa2c a(n) Semaphore waitIfCurtailedSignal
frame 0xbfa5aa44 a(n) Semaphore critical:
frame 0xbfa5aa60 a(n) RecursionLock critical:
frame 0xbfa5aa84 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa5aa98 a(n) CatCOIntegerKeyWeakDictionary myEventTable
frame 0xbfa5aac0 a(n) CatCOIntegerKeyWeakDictionary become:
frame 0xbfa5aae4 a(n) BlockClosure [] in WeakDictionary>>changeCapacityTo:
frame 0xbfa5ab00 a(n) RecursionLock critical:
frame 0xbfa5ab18 a(n) CatCOIntegerKeyWeakDictionary changeCapacityTo:
frame 0xbfa5ab2c a(n) CatCOIntegerKeyWeakDictionary rehash
frame 0xbfa5ab50 a(n) BlockClosure [] in WeakDictionary>>finalizeElements
frame 0xbfa5ab6c a(n) BlockClosure ensure:
frame 0xbfa5ab8c a(n) BlockClosure [] in RecursionLock>>critical:
frame 0xbfa5aba8 a(n) BlockClosure ensure:
frame 0xbfa5abc0 a(n) Semaphore critical:
frame 0xbfa5abdc a(n) RecursionLock critical:
frame 0xbfa5abf4 a(n) CatCOIntegerKeyWeakDictionary finalizeElements
frame 0xbfa5ac10 a(n) CatCOIntegerKeyWeakDictionary update:with:from:
frame 0xbfa5ac34 a(n) WeakArray changed:with:
frame 0xbfa5ac4c a(n) WeakArray changed:
frame 0xbfa5ac60 a(n) WeakArray mourn
frame 0xbfa5ac80 a(n) BlockClosure [] in WeakArray
class>>innerFinalizationLoopWith:
frame 0xbfa5ac9c a(n) BlockClosure on:do:
frame 0xbfa5acb4 a Class (WeakArray) innerFinalizationLoopWith:
frame 0xbfa5acd4 a(n) BlockClosure [] in WeakArray
class>>outerFinalizationLoop
frame 0xbfa5acf0 a(n) BlockClosure on:do:
frame 0xbfa5ad08 a(n) BlockClosure [] in Process class>>forBlock:priority:

process 0x84687f4 priority: 90

frame 0xbfa57788 a(n) Semaphore waitIfCurtailedSignal
frame 0xbfa577a0 a(n) Semaphore critical:
frame 0xbfa577bc a(n) RecursionLock critical:
frame 0xbfa577e0 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa577f4 a(n) IdentityDictionary myEventTable
frame 0xbfa5781c a(n) IdentityDictionary become:
frame 0xbfa57838 a(n) IdentityDictionary changeCapacityTo:
frame 0xbfa5784c a(n) IdentityDictionary grow
frame 0xbfa57868 a(n) IdentityDictionary fullCheck
frame 0xbfa57888 a(n) IdentityDictionary at:put:
frame 0xbfa578a4 a(n) IndexedFileMessageCatalog cacheAt:put:
frame 0xbfa578c4 a(n) IndexedFileMessageCatalog at:
frame 0xbfa578dc a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57904 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57924 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa5794c a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57964 a Class (MessageCatalog) lookUp:
frame 0xbfa5797c a(n) UserMessage asString
frame 0xbfa5799c a(n) UserMessage expandMacrosWithArguments:
frame 0xbfa579b4 a(n) UserMessage expandMacrosWith:
frame 0xbfa579c8 a(n) UnhandledException description
frame 0xbfa579e8 a(n) UnhandledException defaultAction
frame 0xbfa57a08 a(n) UnhandledException performHandler:
frame 0xbfa57a24 a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa57a3c a(n) UnhandledException propagateFrom:
frame 0xbfa57a50 a(n) UnhandledException propagate
frame 0xbfa57a64 a(n) UnhandledException raiseSignal
frame 0xbfa57a78 a(n) OsInvalidArgumentsError noHandler
frame 0xbfa57a8c a(n) OsInvalidArgumentsError defaultAction
frame 0xbfa57aac a(n) OsInvalidArgumentsError performHandler:
frame 0xbfa57ac8 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa57ae0 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa57af4 a(n) OsInvalidArgumentsError propagate
frame 0xbfa57b08 a(n) OsInvalidArgumentsError raiseSignal
frame 0xbfa57b24 a(n) Signal raiseRequestWith:errorString:
frame 0xbfa57b40 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa57b54 a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa57b6c a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa57b84 a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa57ba0 a(n) PositionalIOBuffer setPosition:
frame 0xbfa57bc4 a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa57bdc a(n) ExternalReadStream setPosition:
frame 0xbfa57bf8 a(n) ExternalReadStream position:
frame 0xbfa57c10 a(n) EncodedStream position:
frame 0xbfa57c30 a(n) IndexedFileMessageCatalog at:
frame 0xbfa57c48 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57c70 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57c90 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa57cb8 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57cd0 a Class (MessageCatalog) lookUp:
frame 0xbfa57ce8 a(n) UserMessage asString
frame 0xbfa57d08 a(n) UserMessage expandMacrosWithArguments:
frame 0xbfa6269c a(n) UserMessage expandMacrosWith:
frame 0xbfa626b0 a(n) UnhandledException description
frame 0xbfa626d0 a(n) UnhandledException defaultAction
frame 0xbfa626f0 a(n) UnhandledException performHandler:
frame 0xbfa6270c a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa62724 a(n) UnhandledException propagateFrom:
frame 0xbfa62738 a(n) UnhandledException propagate
frame 0xbfa6274c a(n) UnhandledException raiseSignal
frame 0xbfa62760 a(n) OsInvalidArgumentsError noHandler
frame 0xbfa62774 a(n) OsInvalidArgumentsError defaultAction
frame 0xbfa62794 a(n) OsInvalidArgumentsError performHandler:
frame 0xbfa627b0 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa627c8 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa627dc a(n) OsInvalidArgumentsError propagate
frame 0xbfa627f0 a(n) OsInvalidArgumentsError raiseSignal
frame 0xbfa6280c a(n) Signal raiseRequestWith:errorString:
frame 0xbfa62828 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa6283c a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa62854 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa6286c a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62888 a(n) PositionalIOBuffer setPosition:
frame 0xbfa628ac a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa628c4 a(n) ExternalReadStream setPosition:
frame 0xbfa628e0 a(n) ExternalReadStream position:
frame 0xbfa628f8 a(n) EncodedStream position:
frame 0xbfa62918 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62930 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62958 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62978 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa629a0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa629b8 a Class (MessageCatalog) lookUp:
frame 0xbfa629d0 a(n) UserMessage asString
frame 0xbfa629e8 a(n) Signal description
frame 0xbfa629fc a(n) Signal errorString
frame 0xbfa62a14 a Class (UnixDiskFileAccessor) primErrorDescriptionFor:
frame 0xbfa62a30 a Class (UnixDiskFileAccessor) errorDescriptionFor:
frame 0xbfa62a44 a(n) UnixDiskFileAccessor errorString
frame 0xbfa62a68 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa62a7c a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa62a94 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa62aac a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62ac8 a(n) PositionalIOBuffer setPosition:
frame 0xbfa62aec a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa62b04 a(n) ExternalReadStream setPosition:
frame 0xbfa62b20 a(n) ExternalReadStream position:
frame 0xbfa62b38 a(n) EncodedStream position:
frame 0xbfa62b58 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62b70 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62b98 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62bb8 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa62be0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa62bf8 a Class (MessageCatalog) lookUp:
frame 0xbfa62c10 a(n) UserMessage asString
frame 0xbfa62c24 a(n) EmergencyWindow emergencyHelpString
frame 0xbfa62c38 a(n) EmergencyWindow initialize
frame 0xbfa62c4c a Class (EmergencyWindow) new
frame 0xbfa62c6c a Class (EmergencyWindow)
openNewIn:withType:backgroundColor:
frame 0xbfa62c90 a Class (EmergencyWindow) openNewIn:withType:
frame 0xbfa62ca8 a Class (EmergencyWindow) openNewIn:
frame 0xbfa62cc0 a Class (EmergencyWindow) open
frame 0xbfa62cd4 a(n) BlockClosure [] in
EventSensor>>keyAt:character:alternative:down:
frame 0xbfa62cf0 a(n) BlockClosure on:do:
frame 0xbfa62d08 a(n) BlockClosure [] in Process class>>forBlock:priority:


Reply | Threaded
Open this post in threaded view
|

RE: [Bug?] Global EventTable, debugger and deadlocks

Paul Baumann
Interesting, I hadn't seen this variation of the problem before. It is
more common to see semaphore waits affecting stack dumping while
printing objects. Someone will probably respond with a good workaround
for this specific problem, I'll present a general workaround. Here is a
method to avoid having stack dumping (or debugging) code get stuck
waiting for semaphores (that it may never gain access to). It wasn't
clear from the stack just where you'd insert this code to avoid this
problem. Code like this is usually used by the stack dumper (or
debugger) while trying to display stack frame context.

[Semaphore new wait. 'hi'] insteadOfWaitingDo: [ 'bye' ]
'bye'

BlockClosure>>insteadOfWaitingDo: alternativeBlock
        "Evaluate the receiver. If the receiver waits for a semaphore
then stop waiting and evaluate
         oneArgBlock instead. This was written to avoid interruption
while dumping stacks. -plb2007.01.31"

        | kickWhile myProcess kicker |
        kickWhile := true asValue.
        myProcess := Processor activeProcess.
        kicker := [
                [
                        kickWhile value ifTrue: [
                                myProcess isWaiting ifTrue: [
                                        kickWhile value: false.
                                        myProcess interruptWith:
[SemaphoreWaitInterruption raise].
                                ].
                        ].
                        kickWhile value and: [myProcess isTerminated
not]
                ] whileTrue: [(Delay forMilliseconds: 50) wait].
        ] forkAt: (Processor activePriority + 1 min: 100).
        ^[
                self
                        on: SemaphoreWaitInterruption
                        do: [:ex | ex return: alternativeBlock value ].
        ] ensure: [
                kickWhile value: false.
                kicker terminate.
        ].


Paul Baumann
IntercontinentalExchange | ICE
[hidden email]

-----Original Message-----
From: Holger Kleinsorgen [mailto:[hidden email]]
Sent: Thursday, February 08, 2007 7:57 AM
To: VWNC,
Subject: [Bug?] Global EventTable, debugger and deadlocks

Hi,

while debugging some code I repeatedly encountered a deadlock situation
caused by the global EventTable dictionary and its lock.
While interrupting a process that was about to grow a collection and
entered the lock along the way, the debugger also wanted to enter the
lock, causing a deadlock.

process 0x8464084 priority: 90

frame 0xbfa5aa2c a(n) Semaphore waitIfCurtailedSignal frame 0xbfa5aa44
a(n) Semaphore critical:
frame 0xbfa5aa60 a(n) RecursionLock critical:
frame 0xbfa5aa84 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa5aa98 a(n) CatCOIntegerKeyWeakDictionary myEventTable frame
0xbfa5aac0 a(n) CatCOIntegerKeyWeakDictionary become:
frame 0xbfa5aae4 a(n) BlockClosure [] in
WeakDictionary>>changeCapacityTo:
frame 0xbfa5ab00 a(n) RecursionLock critical:
frame 0xbfa5ab18 a(n) CatCOIntegerKeyWeakDictionary changeCapacityTo:
frame 0xbfa5ab2c a(n) CatCOIntegerKeyWeakDictionary rehash frame
0xbfa5ab50 a(n) BlockClosure [] in WeakDictionary>>finalizeElements
frame 0xbfa5ab6c a(n) BlockClosure ensure:
frame 0xbfa5ab8c a(n) BlockClosure [] in RecursionLock>>critical:
frame 0xbfa5aba8 a(n) BlockClosure ensure:
frame 0xbfa5abc0 a(n) Semaphore critical:
frame 0xbfa5abdc a(n) RecursionLock critical:
frame 0xbfa5abf4 a(n) CatCOIntegerKeyWeakDictionary finalizeElements
frame 0xbfa5ac10 a(n) CatCOIntegerKeyWeakDictionary update:with:from:
frame 0xbfa5ac34 a(n) WeakArray changed:with:
frame 0xbfa5ac4c a(n) WeakArray changed:
frame 0xbfa5ac60 a(n) WeakArray mourn
frame 0xbfa5ac80 a(n) BlockClosure [] in WeakArray
class>>innerFinalizationLoopWith:
frame 0xbfa5ac9c a(n) BlockClosure on:do:
frame 0xbfa5acb4 a Class (WeakArray) innerFinalizationLoopWith:
frame 0xbfa5acd4 a(n) BlockClosure [] in WeakArray
class>>outerFinalizationLoop
frame 0xbfa5acf0 a(n) BlockClosure on:do:
frame 0xbfa5ad08 a(n) BlockClosure [] in Process
class>>forBlock:priority:

process 0x84687f4 priority: 90

frame 0xbfa57788 a(n) Semaphore waitIfCurtailedSignal frame 0xbfa577a0
a(n) Semaphore critical:
frame 0xbfa577bc a(n) RecursionLock critical:
frame 0xbfa577e0 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa577f4 a(n) IdentityDictionary myEventTable frame 0xbfa5781c
a(n) IdentityDictionary become:
frame 0xbfa57838 a(n) IdentityDictionary changeCapacityTo:
frame 0xbfa5784c a(n) IdentityDictionary grow frame 0xbfa57868 a(n)
IdentityDictionary fullCheck frame 0xbfa57888 a(n) IdentityDictionary
at:put:
frame 0xbfa578a4 a(n) IndexedFileMessageCatalog cacheAt:put:
frame 0xbfa578c4 a(n) IndexedFileMessageCatalog at:
frame 0xbfa578dc a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57904 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57924 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa5794c a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57964 a Class (MessageCatalog) lookUp:
frame 0xbfa5797c a(n) UserMessage asString frame 0xbfa5799c a(n)
UserMessage expandMacrosWithArguments:
frame 0xbfa579b4 a(n) UserMessage expandMacrosWith:
frame 0xbfa579c8 a(n) UnhandledException description frame 0xbfa579e8
a(n) UnhandledException defaultAction frame 0xbfa57a08 a(n)
UnhandledException performHandler:
frame 0xbfa57a24 a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa57a3c a(n) UnhandledException propagateFrom:
frame 0xbfa57a50 a(n) UnhandledException propagate frame 0xbfa57a64 a(n)
UnhandledException raiseSignal frame 0xbfa57a78 a(n)
OsInvalidArgumentsError noHandler frame 0xbfa57a8c a(n)
OsInvalidArgumentsError defaultAction frame 0xbfa57aac a(n)
OsInvalidArgumentsError performHandler:
frame 0xbfa57ac8 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa57ae0 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa57af4 a(n) OsInvalidArgumentsError propagate frame 0xbfa57b08
a(n) OsInvalidArgumentsError raiseSignal frame 0xbfa57b24 a(n) Signal
raiseRequestWith:errorString:
frame 0xbfa57b40 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa57b54 a(n) UnixDiskFileAccessor reportErrorProceeding frame
0xbfa57b6c a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa57b84 a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa57ba0 a(n) PositionalIOBuffer setPosition:
frame 0xbfa57bc4 a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa57bdc a(n) ExternalReadStream setPosition:
frame 0xbfa57bf8 a(n) ExternalReadStream position:
frame 0xbfa57c10 a(n) EncodedStream position:
frame 0xbfa57c30 a(n) IndexedFileMessageCatalog at:
frame 0xbfa57c48 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57c70 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57c90 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa57cb8 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57cd0 a Class (MessageCatalog) lookUp:
frame 0xbfa57ce8 a(n) UserMessage asString frame 0xbfa57d08 a(n)
UserMessage expandMacrosWithArguments:
frame 0xbfa6269c a(n) UserMessage expandMacrosWith:
frame 0xbfa626b0 a(n) UnhandledException description frame 0xbfa626d0
a(n) UnhandledException defaultAction frame 0xbfa626f0 a(n)
UnhandledException performHandler:
frame 0xbfa6270c a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa62724 a(n) UnhandledException propagateFrom:
frame 0xbfa62738 a(n) UnhandledException propagate frame 0xbfa6274c a(n)
UnhandledException raiseSignal frame 0xbfa62760 a(n)
OsInvalidArgumentsError noHandler frame 0xbfa62774 a(n)
OsInvalidArgumentsError defaultAction frame 0xbfa62794 a(n)
OsInvalidArgumentsError performHandler:
frame 0xbfa627b0 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa627c8 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa627dc a(n) OsInvalidArgumentsError propagate frame 0xbfa627f0
a(n) OsInvalidArgumentsError raiseSignal frame 0xbfa6280c a(n) Signal
raiseRequestWith:errorString:
frame 0xbfa62828 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa6283c a(n) UnixDiskFileAccessor reportErrorProceeding frame
0xbfa62854 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa6286c a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62888 a(n) PositionalIOBuffer setPosition:
frame 0xbfa628ac a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa628c4 a(n) ExternalReadStream setPosition:
frame 0xbfa628e0 a(n) ExternalReadStream position:
frame 0xbfa628f8 a(n) EncodedStream position:
frame 0xbfa62918 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62930 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62958 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62978 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa629a0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa629b8 a Class (MessageCatalog) lookUp:
frame 0xbfa629d0 a(n) UserMessage asString frame 0xbfa629e8 a(n) Signal
description frame 0xbfa629fc a(n) Signal errorString frame 0xbfa62a14 a
Class (UnixDiskFileAccessor) primErrorDescriptionFor:
frame 0xbfa62a30 a Class (UnixDiskFileAccessor) errorDescriptionFor:
frame 0xbfa62a44 a(n) UnixDiskFileAccessor errorString frame 0xbfa62a68
a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa62a7c a(n) UnixDiskFileAccessor reportErrorProceeding frame
0xbfa62a94 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa62aac a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62ac8 a(n) PositionalIOBuffer setPosition:
frame 0xbfa62aec a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa62b04 a(n) ExternalReadStream setPosition:
frame 0xbfa62b20 a(n) ExternalReadStream position:
frame 0xbfa62b38 a(n) EncodedStream position:
frame 0xbfa62b58 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62b70 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62b98 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62bb8 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa62be0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa62bf8 a Class (MessageCatalog) lookUp:
frame 0xbfa62c10 a(n) UserMessage asString frame 0xbfa62c24 a(n)
EmergencyWindow emergencyHelpString frame 0xbfa62c38 a(n)
EmergencyWindow initialize frame 0xbfa62c4c a Class (EmergencyWindow)
new frame 0xbfa62c6c a Class (EmergencyWindow)
openNewIn:withType:backgroundColor:
frame 0xbfa62c90 a Class (EmergencyWindow) openNewIn:withType:
frame 0xbfa62ca8 a Class (EmergencyWindow) openNewIn:
frame 0xbfa62cc0 a Class (EmergencyWindow) open frame 0xbfa62cd4 a(n)
BlockClosure [] in
EventSensor>>keyAt:character:alternative:down:
frame 0xbfa62cf0 a(n) BlockClosure on:do:
frame 0xbfa62d08 a(n) BlockClosure [] in Process
class>>forBlock:priority:
 
 
 
--------------------------------------------------------
This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.  
 

Reply | Threaded
Open this post in threaded view
|

Re: [Bug?] Global EventTable, debugger and deadlocks

Alan Knight-2
In reply to this post by Holger Kleinsorgen-4
Yes, that can happen. That particular version will not happen in 7.5, because the ability to have dependents and events on collections that would use the global registries has been removed. This is not a general solution for all such deadlocks, but does remove one of the major sources of it, because collections use become: to grow, and this would in previous releases lock the global event table.

At 07:57 AM 2/8/2007, Holger Kleinsorgen wrote:
Hi,

while debugging some code I repeatedly encountered a deadlock situation caused by the global EventTable dictionary and its lock.
While interrupting a process that was about to grow a collection and entered the lock along the way, the debugger also wanted to enter the lock, causing a deadlock.

process 0x8464084 priority: 90

frame 0xbfa5aa2c a(n) Semaphore waitIfCurtailedSignal
frame 0xbfa5aa44 a(n) Semaphore critical:
frame 0xbfa5aa60 a(n) RecursionLock critical:
frame 0xbfa5aa84 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa5aa98 a(n) CatCOIntegerKeyWeakDictionary myEventTable
frame 0xbfa5aac0 a(n) CatCOIntegerKeyWeakDictionary become:
frame 0xbfa5aae4 a(n) BlockClosure [] in WeakDictionary>>changeCapacityTo:
frame 0xbfa5ab00 a(n) RecursionLock critical:
frame 0xbfa5ab18 a(n) CatCOIntegerKeyWeakDictionary changeCapacityTo:
frame 0xbfa5ab2c a(n) CatCOIntegerKeyWeakDictionary rehash
frame 0xbfa5ab50 a(n) BlockClosure [] in WeakDictionary>>finalizeElements
frame 0xbfa5ab6c a(n) BlockClosure ensure:
frame 0xbfa5ab8c a(n) BlockClosure [] in RecursionLock>>critical:
frame 0xbfa5aba8 a(n) BlockClosure ensure:
frame 0xbfa5abc0 a(n) Semaphore critical:
frame 0xbfa5abdc a(n) RecursionLock critical:
frame 0xbfa5abf4 a(n) CatCOIntegerKeyWeakDictionary finalizeElements
frame 0xbfa5ac10 a(n) CatCOIntegerKeyWeakDictionary update:with:from:
frame 0xbfa5ac34 a(n) WeakArray changed:with:
frame 0xbfa5ac4c a(n) WeakArray changed:
frame 0xbfa5ac60 a(n) WeakArray mourn
frame 0xbfa5ac80 a(n) BlockClosure [] in WeakArray class>>innerFinalizationLoopWith:
frame 0xbfa5ac9c a(n) BlockClosure on:do:
frame 0xbfa5acb4 a Class (WeakArray) innerFinalizationLoopWith:
frame 0xbfa5acd4 a(n) BlockClosure [] in WeakArray class>>outerFinalizationLoop
frame 0xbfa5acf0 a(n) BlockClosure on:do:
frame 0xbfa5ad08 a(n) BlockClosure [] in Process class>>forBlock:priority:

process 0x84687f4 priority: 90

frame 0xbfa57788 a(n) Semaphore waitIfCurtailedSignal
frame 0xbfa577a0 a(n) Semaphore critical:
frame 0xbfa577bc a(n) RecursionLock critical:
frame 0xbfa577e0 a(n) EphemeronDictionary at:ifAbsent:
frame 0xbfa577f4 a(n) IdentityDictionary myEventTable
frame 0xbfa5781c a(n) IdentityDictionary become:
frame 0xbfa57838 a(n) IdentityDictionary changeCapacityTo:
frame 0xbfa5784c a(n) IdentityDictionary grow
frame 0xbfa57868 a(n) IdentityDictionary fullCheck
frame 0xbfa57888 a(n) IdentityDictionary at:put:
frame 0xbfa578a4 a(n) IndexedFileMessageCatalog cacheAt:put:
frame 0xbfa578c4 a(n) IndexedFileMessageCatalog at:
frame 0xbfa578dc a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57904 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57924 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa5794c a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57964 a Class (MessageCatalog) lookUp:
frame 0xbfa5797c a(n) UserMessage asString
frame 0xbfa5799c a(n) UserMessage expandMacrosWithArguments:
frame 0xbfa579b4 a(n) UserMessage expandMacrosWith:
frame 0xbfa579c8 a(n) UnhandledException description
frame 0xbfa579e8 a(n) UnhandledException defaultAction
frame 0xbfa57a08 a(n) UnhandledException performHandler:
frame 0xbfa57a24 a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa57a3c a(n) UnhandledException propagateFrom:
frame 0xbfa57a50 a(n) UnhandledException propagate
frame 0xbfa57a64 a(n) UnhandledException raiseSignal
frame 0xbfa57a78 a(n) OsInvalidArgumentsError noHandler
frame 0xbfa57a8c a(n) OsInvalidArgumentsError defaultAction
frame 0xbfa57aac a(n) OsInvalidArgumentsError performHandler:
frame 0xbfa57ac8 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa57ae0 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa57af4 a(n) OsInvalidArgumentsError propagate
frame 0xbfa57b08 a(n) OsInvalidArgumentsError raiseSignal
frame 0xbfa57b24 a(n) Signal raiseRequestWith:errorString:
frame 0xbfa57b40 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa57b54 a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa57b6c a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa57b84 a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa57ba0 a(n) PositionalIOBuffer setPosition:
frame 0xbfa57bc4 a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa57bdc a(n) ExternalReadStream setPosition:
frame 0xbfa57bf8 a(n) ExternalReadStream position:
frame 0xbfa57c10 a(n) EncodedStream position:
frame 0xbfa57c30 a(n) IndexedFileMessageCatalog at:
frame 0xbfa57c48 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa57c70 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa57c90 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa57cb8 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa57cd0 a Class (MessageCatalog) lookUp:
frame 0xbfa57ce8 a(n) UserMessage asString
frame 0xbfa57d08 a(n) UserMessage expandMacrosWithArguments:
frame 0xbfa6269c a(n) UserMessage expandMacrosWith:
frame 0xbfa626b0 a(n) UnhandledException description
frame 0xbfa626d0 a(n) UnhandledException defaultAction
frame 0xbfa626f0 a(n) UnhandledException performHandler:
frame 0xbfa6270c a(n) UnhandledException propagatePrivateFrom:
frame 0xbfa62724 a(n) UnhandledException propagateFrom:
frame 0xbfa62738 a(n) UnhandledException propagate
frame 0xbfa6274c a(n) UnhandledException raiseSignal
frame 0xbfa62760 a(n) OsInvalidArgumentsError noHandler
frame 0xbfa62774 a(n) OsInvalidArgumentsError defaultAction
frame 0xbfa62794 a(n) OsInvalidArgumentsError performHandler:
frame 0xbfa627b0 a(n) OsInvalidArgumentsError propagatePrivateFrom:
frame 0xbfa627c8 a(n) OsInvalidArgumentsError propagateFrom:
frame 0xbfa627dc a(n) OsInvalidArgumentsError propagate
frame 0xbfa627f0 a(n) OsInvalidArgumentsError raiseSignal
frame 0xbfa6280c a(n) Signal raiseRequestWith:errorString:
frame 0xbfa62828 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa6283c a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa62854 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa6286c a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62888 a(n) PositionalIOBuffer setPosition:
frame 0xbfa628ac a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa628c4 a(n) ExternalReadStream setPosition:
frame 0xbfa628e0 a(n) ExternalReadStream position:
frame 0xbfa628f8 a(n) EncodedStream position:
frame 0xbfa62918 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62930 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62958 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62978 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa629a0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa629b8 a Class (MessageCatalog) lookUp:
frame 0xbfa629d0 a(n) UserMessage asString
frame 0xbfa629e8 a(n) Signal description
frame 0xbfa629fc a(n) Signal errorString
frame 0xbfa62a14 a Class (UnixDiskFileAccessor) primErrorDescriptionFor:
frame 0xbfa62a30 a Class (UnixDiskFileAccessor) errorDescriptionFor:
frame 0xbfa62a44 a(n) UnixDiskFileAccessor errorString
frame 0xbfa62a68 a Class (UnixDiskFileAccessor) reportProceedingOn:
frame 0xbfa62a7c a(n) UnixDiskFileAccessor reportErrorProceeding
frame 0xbfa62a94 a(n) UnixDiskFileAccessor primSeekTo:
frame 0xbfa62aac a(n) UnixDiskFileAccessor seekTo:
frame 0xbfa62ac8 a(n) PositionalIOBuffer setPosition:
frame 0xbfa62aec a(n) PositionalIOBuffer readPosition:setOffset:
frame 0xbfa62b04 a(n) ExternalReadStream setPosition:
frame 0xbfa62b20 a(n) ExternalReadStream position:
frame 0xbfa62b38 a(n) EncodedStream position:
frame 0xbfa62b58 a(n) IndexedFileMessageCatalog at:
frame 0xbfa62b70 a(n) IndexedFileMessageCatalog lookUp:
frame 0xbfa62b98 a Class (IndexedFileMessageCatalog) lookUp:
frame 0xbfa62bb8 a(n) BlockClosure [] in BlockClosure>>unboundMethod
frame 0xbfa62be0 a Class (MessageCatalog) allSubclassesDo:
frame 0xbfa62bf8 a Class (MessageCatalog) lookUp:
frame 0xbfa62c10 a(n) UserMessage asString
frame 0xbfa62c24 a(n) EmergencyWindow emergencyHelpString
frame 0xbfa62c38 a(n) EmergencyWindow initialize
frame 0xbfa62c4c a Class (EmergencyWindow) new
frame 0xbfa62c6c a Class (EmergencyWindow) openNewIn:withType:backgroundColor:
frame 0xbfa62c90 a Class (EmergencyWindow) openNewIn:withType:
frame 0xbfa62ca8 a Class (EmergencyWindow) openNewIn:
frame 0xbfa62cc0 a Class (EmergencyWindow) open
frame 0xbfa62cd4 a(n) BlockClosure [] in EventSensor>>keyAt:character:alternative:down:
frame 0xbfa62cf0 a(n) BlockClosure on:do:
frame 0xbfa62d08 a(n) BlockClosure [] in Process class>>forBlock:priority:


--
Alan Knight [|], Cincom Smalltalk Development

"The Static Typing Philosophy: Make it fast. Make it right. Make it run." - Niall Ross
Reply | Threaded
Open this post in threaded view
|

insteadOfWaitingDo: [Re: [Bug?] Global EventTable, debugger and deadlocks]

Reinout Heeck
In reply to this post by Paul Baumann

On Feb 8, 2007, at 3:03 PM, Paul Baumann wrote:

>
> [Semaphore new wait. 'hi'] insteadOfWaitingDo: [ 'bye' ]
> 'bye'
>
> BlockClosure>>insteadOfWaitingDo: alternativeBlock
> "Evaluate the receiver. If the receiver waits for a semaphore
> then stop waiting and evaluate
> oneArgBlock instead. This was written to avoid interruption
> while dumping stacks. -plb2007.01.31"
>
> | kickWhile myProcess kicker |
> kickWhile := true asValue.
> myProcess := Processor activeProcess.
> kicker := [
> [
> kickWhile value ifTrue: [
> myProcess isWaiting ifTrue: [
> kickWhile value: false.
> myProcess interruptWith:
> [SemaphoreWaitInterruption raise].
> ].
> ].
> kickWhile value and: [myProcess isTerminated
> not]
> ] whileTrue: [(Delay forMilliseconds: 50) wait].
> ] forkAt: (Processor activePriority + 1 min: 100).
> ^[
> self
> on: SemaphoreWaitInterruption
> do: [:ex | ex return: alternativeBlock value ].
> ] ensure: [
> kickWhile value: false.
> kicker terminate.
> ].
>
>


Why is kickWhile a valueholder? I feel like some trick is being  
deployed that is going over my head...

As to the multitreading I can suggest that the kicker need only run  
at the same priority as myProcess. This would change the semantics  
slightly but note that this might be cleaner: the Kicker is not  
needed as long as cpu is used by other processes (particularly  
myProcess and its potential child processes). Now I come to think of  
it: this means you don't need the delay and the #isWaiting test  
either :-)

Hmmm this also suggests you can remove the loop, something like



BlockClosure>>insteadOfWaitingDo: alternativeBlock
        | myProcess kick |
        myProcess := Processor activeProcess.
        kick := true.
        [ kick ifTrue: [myProcess interruptWith: [SemaphoreWaitInterruption  
raise]].
        ] fork.
        ^[ self on: SemaphoreWaitInterruption
                        do: [:ex | ex return: alternativeBlock value ].
        ] ensure: [kick := false].




Cheers,

R
-

Reply | Threaded
Open this post in threaded view
|

RE: insteadOfWaitingDo: [Re: [Bug?] Global EventTable, debugger and deadlocks]

Paul Baumann
Yea, I knew the version I showed wasn't optimal for VW. Thanks for
refining it. The kickWhile value holder isn't necessary for VW like it
would be for VA--it is a technique I tend to use out of habit more than
necessity; it is a trick for portability with dialects lacking true
block closures.

My first implementation used a new process at the same priority and
didn't use the delay. The version I showed was a revision that got the
forked "kicker" processes to cleanup faster. With the earlier version
there was a low-memory exception dump and the memory added by
longer-lived kicker processes (nested too) caused dumping to appear to
hang the image. It was an odd scenario but was easily reproduced in our
environment. You might consider how long the forked processes could live
and how the forked processes (there could be hundreds if not cleaned up)
would show in concurrent stack dumps. I think you'll want to #terminate
them in the ensure block instead of allowing them to clean up on their
own.

I knew it could be done without the loop but I took an easy-to-implement
route that had the perceived benefit of not being affected by
time-slicing load balancers--rare as they are. I didn't want to assume
that the forking process was switched for only the traditional reasons
or that processes are scheduled by the default sequence. I wasn't sure
if callins would affect it. Details like that aren't really a problem
for the anticipated uses of this code though. Another way to say it is
that your version has the benefit of kicking processes interrupted for
reasons other than semaphore waits--so long as the forked process gets
some attention. Showing the code with the Delay makes it obvious that
someone can customize the time that is waited, but that feature isn't
required nor was it shown implemented as configurable.

I figured someone might also propose a way to avoid the cost of forking
a separate "kicker" process by scheduling work for some existing VW
specific process. There are many ways to skin this cat. I'd experimented
with one that didn't use #interruptWith: too. I just threw out the one I
had readily available and that has had some use.

Regards,

Paul Baumann
IntercontinentalExchange | ICE
[hidden email]

-----Original Message-----
From: Reinout Heeck [mailto:[hidden email]]
Sent: Thursday, February 08, 2007 10:22 AM
To: VWNC,
Subject: insteadOfWaitingDo: [Re: [Bug?] Global EventTable, debugger and
deadlocks]


On Feb 8, 2007, at 3:03 PM, Paul Baumann wrote:

>
> [Semaphore new wait. 'hi'] insteadOfWaitingDo: [ 'bye' ] 'bye'
>
> BlockClosure>>insteadOfWaitingDo: alternativeBlock
> "Evaluate the receiver. If the receiver waits for a semaphore
then
> stop waiting and evaluate
> oneArgBlock instead. This was written to avoid interruption
while

> dumping stacks. -plb2007.01.31"
>
> | kickWhile myProcess kicker |
> kickWhile := true asValue.
> myProcess := Processor activeProcess.
> kicker := [
> [
> kickWhile value ifTrue: [
> myProcess isWaiting ifTrue: [
> kickWhile value: false.
> myProcess interruptWith:
> [SemaphoreWaitInterruption raise].
> ].
> ].
> kickWhile value and: [myProcess isTerminated
not]

> ] whileTrue: [(Delay forMilliseconds: 50) wait].
> ] forkAt: (Processor activePriority + 1 min: 100).
> ^[
> self
> on: SemaphoreWaitInterruption
> do: [:ex | ex return: alternativeBlock value ].
> ] ensure: [
> kickWhile value: false.
> kicker terminate.
> ].
>
>


Why is kickWhile a valueholder? I feel like some trick is being  
deployed that is going over my head...

As to the multitreading I can suggest that the kicker need only run  
at the same priority as myProcess. This would change the semantics  
slightly but note that this might be cleaner: the Kicker is not  
needed as long as cpu is used by other processes (particularly  
myProcess and its potential child processes). Now I come to think of  
it: this means you don't need the delay and the #isWaiting test  
either :-)

Hmmm this also suggests you can remove the loop, something like



BlockClosure>>insteadOfWaitingDo: alternativeBlock
        | myProcess kick |
        myProcess := Processor activeProcess.
        kick := true.
        [ kick ifTrue: [myProcess interruptWith:
[SemaphoreWaitInterruption  
raise]].
        ] fork.
        ^[ self on: SemaphoreWaitInterruption
                        do: [:ex | ex return: alternativeBlock value ].
        ] ensure: [kick := false].




Cheers,

R
-
 
 
 
--------------------------------------------------------
This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.  
 

Reply | Threaded
Open this post in threaded view
|

Re: insteadOfWaitingDo: [Re: [Bug?] Global EventTable, debugger and deadlocks]

Reinout Heeck
Thanks,
I don't have much experience with platform neutral coding so it's  
nice to get some basics explained.


R
-