Debugger hangs vm on step into

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

Debugger hangs vm on step into

Alain Rastoul-2
Hi

I wanted to step into SharedQueue code, but got a hanged vm on simple
test code below.
It works fine in Pharo 3 but hangs in Pharo4-40611 and Pharo5-50029,
it does not hang in squeak 4.5 but the Monitor code is not the same.

In a playgound, execute the first two lines of code then select
the third line and 'Debug it' (right click menu option) to step into it.

q := SharedQueue new .
q nextPut: 1 .
q next.


Everything goes fine until stepping into 'aBlock value' in
Monitor>>critical:
critical: aBlock

        ^[
        self enter.
Hangs here >>>>aBlock value<<<<<< ]
                ensure: [self exit].

The vm get hanged and can be interrupted only once, then it is
completely hanged.

I once got an error message Error: Monitor access violation message and
a stack trace in debug log before hanging
but was unable to reproduce it (something related to effectiveProcess?)

--- The full stack ---
Monitor(Object)>>error:
Monitor>>checkOwnerProcess
Monitor>>waitWhile:for:maxMilliseconds:
Monitor>>waitWhile:for:
Monitor>>waitWhile:
[
monitor waitWhile: [ items isEmpty ].
items removeFirst ] in SharedQueue>>next
[
self enter.
aBlock value ] in Monitor>>critical:
BlockClosure>>ensure:
Monitor>>critical:
SharedQueue>>next
UndefinedObject>>DoIt
CompiledMethod>>valueWithReceiver:arguments:
[ aCompiledMethod valueWithReceiver: anObject arguments: (evalContext
ifNil: [ #() ] ifNotNil: [ {evalContext} ]) ] in
RubSmalltalkEditor>>debug:receiver:in:
[
self value.
Processor terminateActive ] in BlockClosure>>newProcess
-------------------------------------------------------------------------------

Can someone have a look and confirm it is a bug before I open a bug entry ?
And/or give me hints on how to debug this ?
I tried to modify Monitor>>waitWhile: and put a delay, put traces but
still hanging.
DebugSession someInstance stepInto does not hang, but I'm not sure that
the execution flow is the same ...


TIA
--
Regards,

Alain


Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Ben Coman
I tried...
* my usual locked image avoidance hack when playing at this level to comment out calls to #interCyclePause: 
* changing to DelayMillisecondScheduler and DelaySemaphoreSchedulers
...but no luck.

How do mean that "DebugSession someInstance stepInto" does not hang?  How do you get to that point.

I am having a look by putting a haltOnce in DebugSession>>stepInto:
then pressing the <Into> button.

cheers -ben

On Tue, May 5, 2015 at 5:10 PM, Alain Rastoul <[hidden email]> wrote:
Hi

I wanted to step into SharedQueue code, but got a hanged vm on simple test code below.
It works fine in Pharo 3 but hangs in Pharo4-40611 and Pharo5-50029,
it does not hang in squeak 4.5 but the Monitor code is not the same.

In a playgound, execute the first two lines of code then select
the third line and 'Debug it' (right click menu option) to step into it.

q := SharedQueue new .
q nextPut: 1 .
q next.


Everything goes fine until stepping into 'aBlock value' in Monitor>>critical:
critical: aBlock

        ^[
        self enter.
Hangs here >>>>aBlock value<<<<<< ]
                ensure: [self exit].

The vm get hanged and can be interrupted only once, then it is completely hanged.

I once got an error message Error: Monitor access violation message and a stack trace in debug log before hanging
but was unable to reproduce it (something related to effectiveProcess?)

--- The full stack ---
Monitor(Object)>>error:
Monitor>>checkOwnerProcess
Monitor>>waitWhile:for:maxMilliseconds:
Monitor>>waitWhile:for:
Monitor>>waitWhile:
[
monitor waitWhile: [ items isEmpty ].
items removeFirst ] in SharedQueue>>next
[
self enter.
aBlock value ] in Monitor>>critical:
BlockClosure>>ensure:
Monitor>>critical:
SharedQueue>>next
UndefinedObject>>DoIt
CompiledMethod>>valueWithReceiver:arguments:
[ aCompiledMethod valueWithReceiver: anObject arguments: (evalContext ifNil: [ #() ] ifNotNil: [ {evalContext} ]) ] in RubSmalltalkEditor>>debug:receiver:in:
[
self value.
Processor terminateActive ] in BlockClosure>>newProcess
-------------------------------------------------------------------------------

Can someone have a look and confirm it is a bug before I open a bug entry ?
And/or give me hints on how to debug this ?
I tried to modify Monitor>>waitWhile: and put a delay, put traces but still hanging.
DebugSession someInstance stepInto does not hang, but I'm not sure that the execution flow is the same ...


TIA
--
Regards,

Alain



Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Alain Rastoul-2
Le 05/05/2015 12:35, Ben Coman a écrit :
> I tried...
> * my usual locked image avoidance hack when playing at this level to
> comment out calls to #interCyclePause:
> * changing to DelayMillisecondScheduler and DelaySemaphoreSchedulers
> ...but no luck.
>
No luck means you reproduced and were still locked ?

> How do mean that "DebugSession someInstance stepInto" does not hang?  How
> do you get to that point.
sorry I was not clear
I was trying to debug the step into code of the debugger by selecting
the 'DebugSession someInstance stepInto' code in a playground and right
click / debug it, ie I tried to step into the stepinto code by running
the debugger on itself ... It was just a trial, it worked, that's why
I'm not sure of the execution flow
instructive anyway :)


--
Regards,

Alain


Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Ben Coman


On Tue, May 5, 2015 at 7:06 PM, Alain Rastoul <[hidden email]> wrote:
Le 05/05/2015 12:35, Ben Coman a écrit :
I tried...
* my usual locked image avoidance hack when playing at this level to
comment out calls to #interCyclePause:
* changing to DelayMillisecondScheduler and DelaySemaphoreSchedulers
...but no luck.

No luck means you reproduced and were still locked ?

Thats right. I confirm the bug.
 


How do mean that "DebugSession someInstance stepInto" does not hang?  How
do you get to that point.
sorry I was not clear
I was trying to debug the step into code of the debugger by selecting the 'DebugSession someInstance stepInto' code in a playground and right click / debug it, ie I tried to step into the stepinto code by running the debugger on itself ... It was just a trial, it worked, that's why I'm not sure of the execution flow
instructive anyway :)


--
Regards,

Alain



Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Alain Rastoul-2

Thank you

I opened case 15491
https://pharo.fogbugz.com/f/cases/15491/Debugger-hangs-vm-on-step-into
What makes me think the problem is more likely
in the debugger is that it works when you step over
or when you execute the code.
If the problem were in Monitor I think it would raise an error
when executing.
But may be I'm wrong.

--
Regards,

Alain


Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Ben Coman
In reply to this post by Ben Coman
Not sure if this is related, but if you put a haltOnce at the top of SpecDebugger>>updateReceiverInspectorFromContext:
then step down until the 'receiver' temporary variable is set, 
then inspect 'receiver', the system hangs.
cheers -ben

On Tue, May 5, 2015 at 8:08 PM, Ben Coman <[hidden email]> wrote:


On Tue, May 5, 2015 at 7:06 PM, Alain Rastoul <[hidden email]> wrote:
Le 05/05/2015 12:35, Ben Coman a écrit :
I tried...
* my usual locked image avoidance hack when playing at this level to
comment out calls to #interCyclePause:
* changing to DelayMillisecondScheduler and DelaySemaphoreSchedulers
...but no luck.

No luck means you reproduced and were still locked ?

Thats right. I confirm the bug.
 


How do mean that "DebugSession someInstance stepInto" does not hang?  How
do you get to that point.
sorry I was not clear
I was trying to debug the step into code of the debugger by selecting the 'DebugSession someInstance stepInto' code in a playground and right click / debug it, ie I tried to step into the stepinto code by running the debugger on itself ... It was just a trial, it worked, that's why I'm not sure of the execution flow
instructive anyway :)


--
Regards,

Alain




Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Alain Rastoul-2
Le 05/05/2015 14:35, Ben Coman a écrit :
> Not sure if this is related, but if you put a haltOnce at the top of
> SpecDebugger>>updateReceiverInspectorFromContext:
> then step down until the 'receiver' temporary variable is set,
> then inspect 'receiver', the system hangs.
> cheers -ben
>
>
After digging into it, the cause of the hang is now obvious, but the
simplest solution makes me perplex
and does not cover other cases (ProcessLocalVariables, see below).

The problem comes from the display of the object in the lower pane of
the debugger
that locks itself because the monitor is owned by the debugged process.
(the inspector ends up in a call to  xxx>>printOn: aStream to display
the object
and SharedQueue>>printOn: aStream starts with a critical block on the
monitor).
So we could be hanged in various ways : clicking on the debugger stack
on the Sharedqueue context,
opening an inspector on the Sharedqueue etc).
A simple solution is to evaluate the printOn: in the context of the
owner process
in SharedQueue (tested and works), but it is specific to SharedQueue.

When an inspector ask an object to print itself, it does not take into
account
the "effective/owner process " part of the object.

For example for  ProcessLocalVariable (and descendants) it does not work:
|  process variable |
process := [ variable := ProcessLocalVariable value: 'hello world' ]
                forkAt: Processor userInterruptPriority .
variable  value => evaluates to nil
this makes it difficult (impossible ?) to inspect/debug - a workaround
would be to track
the effective process near the host in the inspector (in
AbstractEyeElement?) but
it could be tricky and I do not know implications here.

Any comment/idea/advice is welcome

I can submit the workaround specific to SharedQueue in the meantime.


TIA


--
Regards,

Alain


Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Ben Coman


On Thu, May 7, 2015 at 9:09 PM, Alain Rastoul <[hidden email]> wrote:
Le 05/05/2015 14:35, Ben Coman a écrit :
Not sure if this is related, but if you put a haltOnce at the top of
SpecDebugger>>updateReceiverInspectorFromContext:
then step down until the 'receiver' temporary variable is set,
then inspect 'receiver', the system hangs.
cheers -ben


After digging into it, the cause of the hang is now obvious, but the simplest solution makes me perplex
and does not cover other cases (ProcessLocalVariables, see below).

The problem comes from the display of the object in the lower pane of the debugger
that locks itself because the monitor is owned by the debugged process.
(the inspector ends up in a call to  xxx>>printOn: aStream to display the object
and SharedQueue>>printOn: aStream starts with a critical block on the monitor).
So we could be hanged in various ways : clicking on the debugger stack on the Sharedqueue context,
opening an inspector on the Sharedqueue etc).
A simple solution is to evaluate the printOn: in the context of the owner process
in SharedQueue (tested and works), but it is specific to SharedQueue.



Does the #printOn: really need a monitor?  What is it protecting?

* not the stream,  that is passed in as a parameter from a single thread

* not the class name, that is handled normally

* items size does  "^ lastIndex - firstIndex + 1"  in OrderedCollection, which presumably will be inlined and not interruptible, and even if it could be interrupted part way through the calculation to become inconsistent, the value is only printed, so do we really care?

For reference...
    SharedQueue>>printOn: aStream
  monitor critical: [
  aStream 
  nextPutAll: self class name;
  nextPutAll: ' with ';
  print: items size;
  nextPutAll: ' items' ].

 
When an inspector ask an object to print itself, it does not take into account the "effective/owner process " part of the object.

For example for  ProcessLocalVariable (and descendants) it does not work:
    |  process variable |
    process := [ variable := ProcessLocalVariable value: 'hello world' ]
                forkAt: Processor userInterruptPriority .
    variable  value => evaluates to nil
 
this makes it difficult (impossible ?) to inspect/debug - a workaround would be to track the effective process near the host in the inspector (in AbstractEyeElement?) but it could be tricky and I do not know implications here.


I am not clear on the semantics we want debugging ProcessLocalVariable, however if without forking I do...

    variable := ProcessLocalVariable value: 'hello world'

then inspecting /variable/ shows me only...

    self: a ProcessLocalVariable
    index: 6

And there is no change when forking...

    process := [ 
variable := ProcessLocalVariable value: 'hello world'.
variable inspect.
] fork.

Also, the following works as expected with respect to the /result/ variable.

    |  process variable result |
    process := [ 
  variable := ProcessLocalVariable value: 'hello world'.
  self halt.
  result := variable value.
  ] fork.

So as ProcessLocalVariable is currently displayed in the debugger there seems no problem (?) for what the debugger displays.  

cheers -ben
    

|  process variable result |
process := [ 
variable := ProcessLocalVariable value: 'hello world'.
self halt.
result := variable value.
] fork.
Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Alain Rastoul-2
Le 07/05/2015 18:43, Ben Coman a écrit :
> On Thu, May 7, 2015 at 9:09 PM, Alain Rastoul <[hidden email]> wrote:
>
>> Le 05/05/2015 14:35, Ben Coman a écrit :

>
> Does the #printOn: really need a monitor?  What is it protecting?
>
> * not the stream,  that is passed in as a parameter from a single thread
>
> * not the class name, that is handled normally
>
> * items size does  "^ lastIndex - firstIndex + 1"  in OrderedCollection,
> which presumably will be inlined and not interruptible, and even if it
> could be interrupted part way through the calculation to become
> inconsistent, the value is only printed, so do we really care?
>
Yes may be you are right, removing the critical: block is simpler and it
is probably not very important here.

>
> I am not clear on the semantics we want debugging ProcessLocalVariable,
> however if without forking I do...
>
>      variable := ProcessLocalVariable value: 'hello world'
>
> then inspecting /variable/ shows me only...
>
>      self: a ProcessLocalVariable
>      index: 6
>
> And there is no change when forking...
>
>      process := [
> variable := ProcessLocalVariable value: 'hello world'.
> variable inspect.
> ] fork.
>
> Also, the following works as expected with respect to the /result/ variable.
>
>      |  process variable result |
>      process := [
>    variable := ProcessLocalVariable value: 'hello world'.
>    self halt.
>    result := variable value.
>    ] fork.
>
> So as ProcessLocalVariable is currently displayed in the debugger there
> seems no problem (?) for what the debugger displays.
>
> cheers -ben
>

You will see a difference in inspecting without forking and with forking
if you try to evaluate the variable value, not just open the inspector on it
wihout forking => 'hello world'
with forking => nil

I thought of ProcessLocalVariable because I spent some time few month
ago trying to debug a ZnServer and ZnCurrentServerSession  is a local
variable, it was my first experiment with the Process local variables.

And I do not like ProcessLocalVariables too much, it was just a thought
about effectiveProcess and  the inspector with critical: blocks that
could lead to hang the image.
The debugger does its best to maintain effectiveProcess when running the
process, not the inspector when evualuating.



--
Regards,

Alain


Reply | Threaded
Open this post in threaded view
|

Re: Debugger hangs vm on step into

Alain Rastoul-2
In reply to this post by Ben Coman
I forgot to thank you  for the feedback
thank you
:)

And slice in the inbox, I removed the critical block in
SharedQueue>>printOn:

--
Regards,

Alain