A few times lately I have noticed I can no longer open a debugger from the Process browser (via Command+d). As soon as I select it the image locks up.
If I break in with Command+. right away I was able to do some minimal tracing. It appears the Process instance I want to debug; his #nextLink is himself. This results an endless recursion when his printing method simply tries to ask his #size.
Incidentally, the Process I wanted to debug was simply waiting on a Semaphore of a network Socket, not actually doing any processing when I tried to debug it, and I can reproduce this problem every time.
I *know* I used to be able to debug these; anyone have any ideas what could be wrong now? thanks..
|
Printing this before pressing Command+d on the Process browser:
Link allSubInstances count: [ : e | e nextLink==e] reports 0. AFTER I press Command+d, I have to press Command+. to interrupt the infinite recursion, which exposes the debugger which is trying to open the debugger on the process I selected (see below for the stack). NOW Link allSubInstances count: [ : e | e nextLink==e] reports 1, and the one instance is the Process I was trying to debug. So, I overrode Process>>#nextLink: setter to guard against setting it to himself and repeating the test. The guard was never hit, but the same condition ('nextLink' referring to itself) still formed. This is impossible since that's the only writer of that variable unless the VM or other low-level mechanism is setting the Process' nextLink. ================ Here's the stack of trying to invoke 'debug' from the Process Browser. A MethodContext is just trying to render its printString as part of Debugger operations but it can't because of the cycle. Any ideas? 5 December 2012 1:34:25.32 pm VM: unix - Smalltalk Image: Squeak4.3 [latest update: #12292] SecurityManager state: Restricted: false FileAccess: true SocketAccess: true Working Dir /home/cmm/Chris/development/Squeak Trusted Dir /home/cmm/Chris/development/Squeak/secure Untrusted Dir /home/cmm/Chris/development/Squeak/My Squeak [] in Semaphore(LinkedList)>>size Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: tally: a Process in [] in DelayWaitTimeout>>wait each: #(25729379) Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 Semaphore(LinkedList)>>do: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: aBlock: [closure] in Semaphore(LinkedList)>>size aLink: a Process in [] in DelayWaitTimeout>>wait Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 Semaphore(LinkedList)>>size Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: tally: #(25729379) Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 Semaphore(SequenceableCollection)>>do:separatedBy: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: elementBlock: [closure] in Semaphore(Collection)>>printElementsOn: separatorBlock: [closure] in Semaphore(Collection)>>printElementsOn: index: nil indexLimiT: nil Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 Semaphore(Collection)>>printElementsOn: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: aStream: a LimitedWriteStream 'a Semaphore(' Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 Semaphore(Collection)>>printOn: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: aStream: a LimitedWriteStream 'a Semaphore(' Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 [] in Semaphore(Object)>>printStringLimitedTo: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: <<error during printing> Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 String class(SequenceableCollection class)>>streamContents:limitedTo: Receiver: String Arguments and temporary variables: blockWithArg: [closure] in Semaphore(Object)>>printStringLimitedTo: sizeLimit: 63 stream: a LimitedWriteStream 'a Semaphore(' Receiver's instance variables: superclass: ArrayedCollection methodDict: a MethodDictionary(size 286) format: 2 instanceVariables: nil organization: ('accessing' byteAt: byteAt:put: byteSize do:toFieldNumber: findA...etc... subclasses: {ByteString . WideString . Symbol} name: #String classPool: a Dictionary(#AsciiOrder->#[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...etc... sharedPools: nil environment: Smalltalk globals "a SystemDictionary with lots of globals" category: #'Collections-Strings' Semaphore(Object)>>printStringLimitedTo: Receiver: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) Arguments and temporary variables: limit: 63 limitedString: nil Receiver's instance variables: firstLink: a Process in [] in DelayWaitTimeout>>wait lastLink: a Process in [] in DelayWaitTimeout>>wait excessSignals: 0 [] in DelayWaitTimeout(Object)>>longPrintOn:limitedTo:indent: Receiver: a DelayWaitTimeout(172748169 msecs; 172583302 msecs remaining) Arguments and temporary variables: aStream: 'delaySemaphore' sizeLimit: 3 indent: MultiByteFileStream: '/home/cmm/Chris/development/Squeak/SqueakDebug.lo...etc... title: 80 index: 2 Receiver's instance variables: delayDuration: 172748169 resumptionTime: 172953821 delaySemaphore: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) beingWaitedOn: true process: a Process in [] in DelayWaitTimeout>>wait expired: false Array(SequenceableCollection)>>withIndexDo: Receiver: #('delayDuration' 'resumptionTime' 'delaySemaphore' 'beingWaitedOn' 'process' 'expired') Arguments and temporary variables: elementAndIndexBlock: [closure] in DelayWaitTimeout(Object)>>longPrintOn:limite...etc... index: 3 indexLimiT: 6 Receiver's instance variables: #('delayDuration' 'resumptionTime' 'delaySemaphore' 'beingWaitedOn' 'process' 'expired') Array(SequenceableCollection)>>doWithIndex: Receiver: #('delayDuration' 'resumptionTime' 'delaySemaphore' 'beingWaitedOn' 'process' 'expired') Arguments and temporary variables: elementAndIndexBlock: [closure] in DelayWaitTimeout(Object)>>longPrintOn:limite...etc... Receiver's instance variables: #('delayDuration' 'resumptionTime' 'delaySemaphore' 'beingWaitedOn' 'process' 'expired') DelayWaitTimeout(Object)>>longPrintOn:limitedTo:indent: Receiver: a DelayWaitTimeout(172748169 msecs; 172583298 msecs remaining) Arguments and temporary variables: aStream: MultiByteFileStream: '/home/cmm/Chris/development/Squeak/SqueakDebug.l...etc... sizeLimit: 80 indent: 2 Receiver's instance variables: delayDuration: 172748169 resumptionTime: 172953821 delaySemaphore: a Semaphore(a Process in [] in DelayWaitTimeout>>wait) beingWaitedOn: true process: a Process in [] in DelayWaitTimeout>>wait expired: false [] in MethodContext>>printDetails: Receiver: [] in DelayWaitTimeout>>wait Arguments and temporary variables: <<error during printing> Receiver's instance variables: sender: BlockClosure>>ensure: pc: 44 stackp: 1 method: (DelayWaitTimeout>>#wait "a CompiledMethod(2835)") closureOrNil: [closure] in DelayWaitTimeout>>wait receiver: a DelayWaitTimeout(172748169 msecs; 172583298 msecs remaining) BlockClosure>>on:do: Receiver: [closure] in MethodContext>>printDetails: Arguments and temporary variables: exception: Error handlerAction: [closure] in BlockClosure>>ifError: handlerActive: true Receiver's instance variables: outerContext: MethodContext>>printDetails: startpc: 197 numArgs: 0 BlockClosure>>ifError: Receiver: [closure] in MethodContext>>printDetails: Arguments and temporary variables: errorHandlerBlock: [closure] in MethodContext>>printDetails: Receiver's instance variables: outerContext: MethodContext>>printDetails: startpc: 197 numArgs: 0 MethodContext>>printDetails: Receiver: [] in DelayWaitTimeout>>wait Arguments and temporary variables: strm: MultiByteFileStream: '/home/cmm/Chris/development/Squeak/SqueakDebug.log'...etc... pe: '<<error during printing>>' str: 'x' pos: 544 Receiver's instance variables: sender: BlockClosure>>ensure: pc: 44 stackp: 1 method: (DelayWaitTimeout>>#wait "a CompiledMethod(2835)") closureOrNil: [closure] in DelayWaitTimeout>>wait receiver: a DelayWaitTimeout(172748169 msecs; 172583294 msecs remaining) MethodContext(ContextPart)>>errorReportOn: Receiver: [] in DelayWaitTimeout>>wait Arguments and temporary variables: strm: MultiByteFileStream: '/home/cmm/Chris/development/Squeak/SqueakDebug.log'...etc... cnt: 1 aContext: [] in DelayWaitTimeout>>wait startPos: 370 Receiver's instance variables: sender: BlockClosure>>ensure: pc: 44 stackp: 1 method: (DelayWaitTimeout>>#wait "a CompiledMethod(2835)") closureOrNil: [closure] in DelayWaitTimeout>>wait receiver: a DelayWaitTimeout(172748169 msecs; 172583286 msecs remaining) SmalltalkImage>>logError:inContext:to: Receiver: Smalltalk Arguments and temporary variables: errMsg: 'Interrupted from the Process Browser' aContext: [] in DelayWaitTimeout>>wait aFilename: 'SqueakDebug.log' ff: MultiByteFileStream: '/home/cmm/Chris/development/Squeak/SqueakDebug.log' Receiver's instance variables: globals: Smalltalk globals "a SystemDictionary with lots of globals" --- The full stack --- [] in Semaphore(LinkedList)>>size Semaphore(LinkedList)>>do: Semaphore(LinkedList)>>size Semaphore(SequenceableCollection)>>do:separatedBy: Semaphore(Collection)>>printElementsOn: Semaphore(Collection)>>printOn: [] in Semaphore(Object)>>printStringLimitedTo: String class(SequenceableCollection class)>>streamContents:limitedTo: Semaphore(Object)>>printStringLimitedTo: [] in DelayWaitTimeout(Object)>>longPrintOn:limitedTo:indent: Array(SequenceableCollection)>>withIndexDo: Array(SequenceableCollection)>>doWithIndex: DelayWaitTimeout(Object)>>longPrintOn:limitedTo:indent: [] in MethodContext>>printDetails: BlockClosure>>on:do: BlockClosure>>ifError: MethodContext>>printDetails: MethodContext(ContextPart)>>errorReportOn: SmalltalkImage>>logError:inContext:to: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SmalltalkImage>>logSqueakError:inContext: [] in Debugger class>>morphicOpenOn:context:label:contents:fullView: BlockClosure>>on:do: Debugger class>>morphicOpenOn:context:label:contents:fullView: MorphicProject(Project)>>dispatchTo:addPrefixAndSend:withArguments: Debugger class>>openOn:context:label:contents:fullView: StandardToolSet class>>debug:context:label:contents:fullView: ToolSet class>>debug:context:label:contents:fullView: Process>>debug:title:full: Process>>debugWithTitle: ProcessBrowser class>>debugProcess: ProcessBrowser>>debugProcess ProcessBrowser>>processListKey:from: PluggableListMorphPlus(PluggableListMorph)>>modifierKeyPressed: PluggableListMorphPlus(PluggableListMorph)>>keyStroke: PluggableListMorphPlus(Morph)>>handleKeystroke: KeyboardEvent>>sentTo: PluggableListMorphPlus(Morph)>>handleEvent: PluggableListMorphPlus(Morph)>>handleFocusEvent: [] in HandMorph>>sendFocusEvent:to:clear: BlockClosure>>on:do: PasteUpMorph>>becomeActiveDuring: HandMorph>>sendFocusEvent:to:clear: HandMorph>>sendEvent:focus:clear: HandMorph>>sendKeyboardEvent: HandMorph>>handleEvent: HandMorph>>processEvents [] in WorldState>>doOneCycleNowFor: Array(SequenceableCollection)>>do: WorldState>>handsDo: WorldState>>doOneCycleNowFor: WorldState>>doOneCycleFor: PasteUpMorph>>doOneCycle [] in Project class>>spawnNewProcess [] in BlockClosure>>newProcess On Wed, Dec 5, 2012 at 11:33 AM, Chris Muller <[hidden email]> wrote: > > A few times lately I have noticed I can no longer open a debugger from the Process browser (via Command+d). As soon as I select it the image locks up. > > If I break in with Command+. right away I was able to do some minimal tracing. It appears the Process instance I want to debug; his #nextLink is himself. This results an endless recursion when his printing method simply tries to ask his #size. > > Incidentally, the Process I wanted to debug was simply waiting on a Semaphore of a network Socket, not actually doing any processing when I tried to debug it, and I can reproduce this problem every time. > > I *know* I used to be able to debug these; anyone have any ideas what could be wrong now? > > thanks.. |
If you set Preferences logDebuggerStackToFile
to false, do things work ok after that?
On 12/5/12 2:46 PM, Chris Muller wrote:
Printing this before pressing Command+d on the Process browser: Link allSubInstances count: [ : e | e nextLink==e] reports 0. AFTER I press Command+d, I have to press Command+. to interrupt the infinite recursion, which exposes the debugger which is trying to open the debugger on the process I selected (see below for the stack). NOW Link allSubInstances count: [ : e | e nextLink==e] reports 1, and the one instance is the Process I was trying to debug. So, I overrode Process>>#nextLink: setter to guard against setting it to himself and repeating the test. The guard was never hit, but the same condition ('nextLink' referring to itself) still formed. This is impossible since that's the only writer of that variable unless the VM or other low-level mechanism is setting the Process' nextLink. ================ Here's the stack of trying to invoke 'debug' from the Process Browser. A MethodContext is just trying to render its printString as part of Debugger operations but it can't because of the cycle. Any ideas? |
Indeed yes. But I also found that the cycle is being created by
primitive 87; Process>>#primitiveResume. Question: Is this valid behavior by the VM? Oh, this is the standard Linux interpreter VM 4.4.7-2357. So, if I hack ProcessBrowser class>>#debugProcess: to simply "undo the damage" wrought by primitiveResume like: ProcessBrowser class>>#debugProcess: | formerNextLink | formerNextLink := aProcess nextLink. self resumeProcess: aProcess. aProcess nextLink: formerNextLink. aProcess debugWithTitle: 'Interrupted from the Process Browser' then I can also debug regardless of the logDebuggerStackToFile setting. I hope someone in the VM community will weigh in; is it valid to create a cycle in the linked-list of one Process? On Wed, Dec 5, 2012 at 2:06 PM, Bob Arning <[hidden email]> wrote: > If you set Preferences logDebuggerStackToFile to false, do things work ok > after that? > > > On 12/5/12 2:46 PM, Chris Muller wrote: > > Printing this before pressing Command+d on the Process browser: > > Link allSubInstances count: [ : e | e nextLink==e] > > reports 0. > > AFTER I press Command+d, I have to press Command+. to interrupt the > infinite recursion, which exposes the debugger which is trying to open > the debugger on the process I selected (see below for the stack). NOW > > Link allSubInstances count: [ : e | e nextLink==e] > > reports 1, and the one instance is the Process I was trying to debug. > > So, I overrode Process>>#nextLink: setter to guard against setting it > to himself and repeating the test. The guard was never hit, but the > same condition ('nextLink' referring to itself) still formed. This is > impossible since that's the only writer of that variable unless the VM > or other low-level mechanism is setting the Process' nextLink. > > ================ > Here's the stack of trying to invoke 'debug' from the Process Browser. > A MethodContext is just trying to render its printString as part of > Debugger operations but it can't because of the cycle. Any ideas? > > > > > |
Well, it will happen if you add something to a
list that's already there. Try this:
| list link | list := LinkedList new. link := Link new. list add: link. list add: link. link explore. So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list. Cheers, Bob On 12/5/12 3:19 PM, Chris Muller wrote:
I hope someone in the VM community will weigh in; is it valid to create a cycle in the linked-list of one Process? |
On 2012-12-05, at 21:49, Bob Arning <[hidden email]> wrote: > Well, it will happen if you add something to a list that's already there. Try this: > > | list link | > list := LinkedList new. > link := Link new. > list add: link. > list add: link. > link explore. > > So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list. > > Cheers, > Bob > > On 12/5/12 3:19 PM, Chris Muller wrote: >> I hope someone in the VM community will weigh in; is it valid to >> create a cycle in the linked-list of one Process? Yes, it's certainly in the use of the primitive, not the primitive itself. Why does the process need to be resumed if it's going to be debugged anyway? - Bert - |
Poking around a little bit I see an oddity I
don't immediately understand. If I do:
[(Delay forSeconds: 100) wait] forkAt: 30 and debug from the ProcessBrowser, the debugger is looking at the call stack from my snippet. If I do: [(Delay forSeconds: 100) wait] forkAt: 50 then use the ProcessBrowser to debug it, the debugger is always in Process>>terminate I don't imagine this is expected behavior. Cheers, Bob On 12/5/12 3:55 PM, Bert Freudenberg
wrote:
On 2012-12-05, at 21:49, Bob Arning [hidden email] wrote:Well, it will happen if you add something to a list that's already there. Try this: | list link | list := LinkedList new. link := Link new. list add: link. list add: link. link explore. So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list. Cheers, Bob On 12/5/12 3:19 PM, Chris Muller wrote:I hope someone in the VM community will weigh in; is it valid to create a cycle in the linked-list of one Process?Yes, it's certainly in the use of the primitive, not the primitive itself. Why does the process need to be resumed if it's going to be debugged anyway? - Bert - |
In reply to this post by Bert Freudenberg
>> Well, it will happen if you add something to a list that's already there. Try this:
>> >> | list link | >> list := LinkedList new. >> link := Link new. >> list add: link. >> list add: link. >> link explore. Sure, that makes perfect sense but... >> So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list. One thing I don't understand; I didn't see the connection from your simple example to what you're saying about resuming a process with lower-priority. Process>>#resume simply calls #primitiveResume, it doesn't add anything to any linked list does it? > Yes, it's certainly in the use of the primitive, not the primitive itself. Bert what do you mean by "the use of the primitive"? It's getting called (by Process>>#resume) I can't think of any other way to use it..? > Why does the process need to be resumed if it's going to be debugged anyway? In looking at the associated code of ProcessBrowser, there is this global IdentityDictionary it maintains called 'SuspendedProcesses'. It is only ever populated by the user selecting "suspend (s)" from the Process list context menu. When a process is suspended this way, if its 'suspendingList' (what is that?) is a Semaphore, then the priority of the Process being suspended is dropped. The reason, according to the comment: "Need to take the priority down below the caller's so that it can keep control after signaling the Semaphore" All this, so that, when eventually the user selects "resume (r)" from the ProcessBrowser list menu, it will be able to restore the original priority of the maybe-it-was-a-Semaphore Process..?? Whatever! Does anyone know Is this still needed or just old junk? |
On 12/5/12 10:40 PM, Chris Muller
wrote:
Well, I don't know where they keep the VM source these days, but when it was included in the image it looked like this:Well, it will happen if you add something to a list that's already there. Try this: | list link | list := LinkedList new. link := Link new. list add: link. list add: link. link explore.Sure, that makes perfect sense but...So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list.One thing I don't understand; I didn't see the connection from your simple example to what you're saying about resuming a process with lower-priority. Process>>#resume simply calls #primitiveResume, it doesn't add anything to any linked list does it? primitiveResume | proc | proc _ self stackTop. "rcvr" "self success: ((self fetchClassOf: proc) = (self splObj: ClassProcess))." successFlag ifTrue: [ self resume: proc ]. resume: aProcess | activeProc activePriority newPriority | self inline: false. activeProc _ self fetchPointer: ActiveProcessIndex ofObject: self schedulerPointer. activePriority _ self quickFetchInteger: PriorityIndex ofObject: activeProc. newPriority _ self quickFetchInteger: PriorityIndex ofObject: aProcess. newPriority > activePriority ifTrue: [ self putToSleep: activeProc. self transferTo: aProcess. ] ifFalse: [ self putToSleep: aProcess. ]. putToSleep: aProcess "Save the given process on the scheduler process list for its priority." | priority processLists processList | priority _ self quickFetchInteger: PriorityIndex ofObject: aProcess. processLists _ self fetchPointer: ProcessListsIndex ofObject: self schedulerPointer. processList _ self fetchPointer: priority - 1 ofObject: processLists. self addLastLink: aProcess toList: processList. addLastLink: proc toList: aList "Add the given process to the given linked list and set the backpointer of process to its new list." | lastLink | (self isEmptyList: aList) ifTrue: [ self storePointer: FirstLinkIndex ofObject: aList withValue: proc. ] ifFalse: [ lastLink _ self fetchPointer: LastLinkIndex ofObject: aList. self storePointer: NextLinkIndex ofObject: lastLink withValue: proc. ]. self storePointer: LastLinkIndex ofObject: aList withValue: proc. self storePointer: MyListIndex ofObject: proc withValue: aList. So, either the process you are resuming or the lower-priority active process will be added to its proper priority list. If that process is already on the list, then your situation could arise. First question: was there anything in Suspended{rocesses when you encountered the error? Was it the process you were resuming?Yes, it's certainly in the use of the primitive, not the primitive itself.Bert what do you mean by "the use of the primitive"? It's getting called (by Process>>#resume) I can't think of any other way to use it..?Why does the process need to be resumed if it's going to be debugged anyway?In looking at the associated code of ProcessBrowser, there is this global IdentityDictionary it maintains called 'SuspendedProcesses'. It is only ever populated by the user selecting "suspend (s)" from the Process list context menu. When a process is suspended this way, if its 'suspendingList' (what is that?) is a Semaphore, then the priority of the Process being suspended is dropped. The reason, according to the comment: "Need to take the priority down below the caller's so that it can keep control after signaling the Semaphore" All this, so that, when eventually the user selects "resume (r)" from the ProcessBrowser list menu, it will be able to restore the original priority of the maybe-it-was-a-Semaphore Process..?? Whatever! Does anyone know Is this still needed or just old junk? Second: can you describe how to recreate the problem? Cheers, Bob |
On 06-12-2012, at 4:00 AM, Bob Arning <[hidden email]> wrote: > [snips] > So, either the process you are resuming or the lower-priority active process will be added to its proper priority list. If that process is already on the list, then your situation could arise. That latter part would be a bug. Though it could be an interesting part of a design for a more time-slice based scheduling system; swap processes every X microseconds, add the process to the list more times to get more % of the cpu. tim -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim fibula: noun, 'a small lie' |
In reply to this post by Chris Muller-3
Well, here's a bit more.
2 timesRepeat: [[[1000 factorial > 0] whileTrue] forkAt: 30]. Now try to debug one of these in the ProcessBrowser - byebye squeak. The problem is in the PB trying to resume a process that's already on the list for its priority in Processor. A similar problem I noted yesterday is that trying to debug a higher-than-UI priority process that was waiting on a semaphore fails as PB signals the semaphore and resumes the process. But the signal lets this process run (to completion, maybe), so nothing left to debug. If you remember when this might have run succesfully, then it might be possible to look for intervening updates that changed something. Cheers, Bob On 12/5/12 10:40 PM, Chris Muller
wrote:
Well, it will happen if you add something to a list that's already there. Try this: | list link | list := LinkedList new. link := Link new. list add: link. list add: link. link explore.Sure, that makes perfect sense but...So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list.One thing I don't understand; I didn't see the connection from your simple example to what you're saying about resuming a process with lower-priority. Process>>#resume simply calls #primitiveResume, it doesn't add anything to any linked list does it?Yes, it's certainly in the use of the primitive, not the primitive itself.Bert what do you mean by "the use of the primitive"? It's getting called (by Process>>#resume) I can't think of any other way to use it..?Why does the process need to be resumed if it's going to be debugged anyway?In looking at the associated code of ProcessBrowser, there is this global IdentityDictionary it maintains called 'SuspendedProcesses'. It is only ever populated by the user selecting "suspend (s)" from the Process list context menu. When a process is suspended this way, if its 'suspendingList' (what is that?) is a Semaphore, then the priority of the Process being suspended is dropped. The reason, according to the comment: "Need to take the priority down below the caller's so that it can keep control after signaling the Semaphore" All this, so that, when eventually the user selects "resume (r)" from the ProcessBrowser list menu, it will be able to restore the original priority of the maybe-it-was-a-Semaphore Process..?? Whatever! Does anyone know Is this still needed or just old junk? |
Commenting out the #resumeProcess: send in #debugProcess: makes this work.
I'm for removing the the whole suspension logic. If you want to suspend the process, why not just debug it, and then proceed when you're done? - Bert - On 2012-12-06, at 19:28, Bob Arning <[hidden email]> wrote: > Well, here's a bit more. > > 2 timesRepeat: [[[1000 factorial > 0] whileTrue] forkAt: 30]. > > Now try to debug one of these in the ProcessBrowser - byebye squeak. The problem is in the PB trying to resume a process that's already on the list for its priority in Processor. > > A similar problem I noted yesterday is that trying to debug a higher-than-UI priority process that was waiting on a semaphore fails as PB signals the semaphore and resumes the process. But the signal lets this process run (to completion, maybe), so nothing left to debug. > > If you remember when this might have run succesfully, then it might be possible to look for intervening updates that changed something. > > Cheers, > Bob > > > On 12/5/12 10:40 PM, Chris Muller wrote: >>>> Well, it will happen if you add something to a list that's already there. Try this: >>>> >>>> | list link | >>>> list := LinkedList new. >>>> link := Link new. >>>> list add: link. >>>> list add: link. >>>> link explore. >>>> >> Sure, that makes perfect sense but... >> >> >>>> So if you send #resume to a process with priority less than the active process, it might happen. Or if you try to suspend the active process, but it's already on a suspended list. >>>> >> One thing I don't understand; I didn't see the connection from your >> simple example to what you're saying about resuming a process with >> lower-priority. Process>>#resume simply calls #primitiveResume, it >> doesn't add anything to any linked list does it? >> >> >>> Yes, it's certainly in the use of the primitive, not the primitive itself. >>> >> Bert what do you mean by "the use of the primitive"? It's getting >> called (by Process>>#resume) I can't think of any other way to use >> it..? >> >> >>> Why does the process need to be resumed if it's going to be debugged anyway? >>> >> In looking at the associated code of ProcessBrowser, there is this >> global IdentityDictionary it maintains called 'SuspendedProcesses'. >> It is only ever populated by the user selecting "suspend (s)" from the >> Process list context menu. When a process is suspended this way, if >> its 'suspendingList' (what is that?) is a Semaphore, then the priority >> of the Process being suspended is dropped. The reason, according to >> the comment: >> >> "Need to take the priority down below the caller's >> so that it can keep control after signaling the Semaphore" >> >> All this, so that, when eventually the user selects "resume (r)" from >> the ProcessBrowser list menu, it will be able to restore the original >> priority of the maybe-it-was-a-Semaphore Process..?? Whatever! >> >> Does anyone know Is this still needed or just old junk? >> >> >> > > |
Free forum by Nabble | Edit this page |