Cannot debug from Process browser

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

Cannot debug from Process browser

Chris Muller-3
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..


Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Chris Muller-3
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..

Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bob Arning-2
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?



Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Chris Muller-3
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?
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bob Arning-2
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?



Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bert Freudenberg

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 -



Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bob Arning-2
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 -







Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Chris Muller-3
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?

Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bob Arning-2

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?
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:

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.


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?

First question: was there anything in Suspended{rocesses when you encountered the error? Was it the process you were resuming?

Second: can you describe how to recreate the problem?

Cheers,
Bob


    



Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

timrowledge

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'



Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bob Arning-2
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?





Reply | Threaded
Open this post in threaded view
|

Re: Cannot debug from Process browser

Bert Freudenberg
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?
>>
>>
>>
>
>