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: |
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. |
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, --
Alan Knight [|], Cincom Smalltalk Development
"The Static Typing Philosophy: Make it fast. Make it right.
Make it run." - Niall Ross
|
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 - |
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 > ] 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. |
Thanks,
I don't have much experience with platform neutral coding so it's nice to get some basics explained. R - |
Free forum by Nabble | Edit this page |