Le 13/11/2017 à 15:56, Ben Coman a écrit :


On Mon, Nov 13, 2017 at 9:32 PM, Thomas Dupriez <[email protected] <mailto:[email protected]>> wrote:



    Le 13/11/2017 à 14:08, Ben Coman a écrit :


    On Mon, Nov 13, 2017 at 8:40 PM, Thomas Dupriez
    <[email protected]
    <mailto:[email protected]>> wrote:

        I dug a bit in this issue. Here are the results:


        # Problem raised by Stephanne
        Code like the following is open in the debugger:

            `myMethod
                1+1. <PROGRAMCOUNTER>
                MyClass new myEvalBlock: [
                    2+2. <CURSOR>
                ].
                3+3.`

        The program counter is on the 1+1, the cursor is at the end
        of the 2+2 line.
        Right-click, "Run to here".
        -> the program counter moves to the 3+3, and does not stop at
        the 2+2 (where the cursor is). Even though the 2+2 does get
        evaluated (the myEvalBlock method evaluates the blocks it
        receives).
        If there was no code after the block, the debugger would jump
        back to the caller of myMethod.

        # Why this happens
        The implementation of RunToHere (source code below) is
        basically to stepOver until the context is different or the
        source code position of the program counter is higher or
        equal to the source code position of the cursor/selection.

        Since the debugger uses stepOver, it executes myEvalBlock
        without stopping, reaches the 3+3 and see it has gone further
        than the source code position of the cursorm so it stops.

        Source code of DebugSession>>#runToSelection:inContext:

            `runToSelection: selectionInterval inContext: aContext
                "Attempt to step over instructions in selectedContext
        until the
                execution reaches the selected instruction. This
        happens when the
                program counter passes the begining of selectionInterval.

                A not nill and valid interval is expected."

                (self pcRangeForContext: aContext) first >=
        selectionInterval first
                    ifTrue: [ ^self ].
                self stepOver: aContext.
                [ aContext == self interruptedContext and: [ (self
        pcRangeForContext: aContext) first < selectionInterval first ] ]
                    whileTrue: [ self stepOver: aContext ]`

        # Observations and thoughts
        - Replacing the stepOver with a stepInto -> This made the
        RunToHere stops when resolving the 'new' message (because the
        context changes).


    Thanks for looking into this Thomas.
    What happens if you use stepThrough rather than stepInto?

    cheers -ben

    Using `stepThrough: aContext` instead of `stepInto: aContext`, the
    RunToHere in the block stops at the intended place: the 2+2.
    Printing the sequence of `self pcRangeForContext: aContext` yields
    the following. It doesn't show precisely the stop in the block,
    and instead shows an interval encompassing the whole block. That's
    what I was using to see where the execution was going during the
    RunToHere loop so I guess that's not a precise enough indicator
    for this situation...
    (21 to: 22)(34 to: 36)(49 to: 60)(38 to: 60)(38 to: 60)

    I also tried the case where the block does not get evaluated
    (changing myEvalBlock so that it does nothing). In this situation,
    the RunToHere with a stepThrough ends up at the intended place,
    the 3+3.

    So... just use stepThrough for the RunToHere I guess?


Seems like expected behaviour.
Could you create an Issue/Pull Request to provide some concrete code to review?

Now the trick will be if you can devise some tests to go with this.
For examples perhaps look at senders of newDebugSessionNamed:startedAt:
including SpecDebugger>>testBasic.

cheers -ben

I opened an issue on FogBugz: https://pharo.fogbugz.com/f/cases/20687/

Attached are the file out of the test code (MyClass.st) and the fixed runToSelection:inContext: (DebugSession-runToSelectioninContext).
I'll make a pull request tomorrow.

For the test, I'm thinking about something like the following, that checks the source code position of the pc after the runToSelection. (It's not working yet) Now that I think of it, the source code position of the pc will maybe be the whole block (as experienced earlier) so this approach may end up not working.
I'll come back to that tomorrow.

Draft for a test:
    `testRunToSelectionInContext
    |context_ process_ session_|
    "The variable names have an underscore to distinguish them from those declared in the setUp method of this TestCase (DebuggerModelTest), which are not suited for this test (because not making a debug session out of suitable code)"
    context_ := [1+1.
        self evalBlock:[2+2].
        3+3.
    ] asContext.
    process_ := Process
        forContext: context_
        priority: Processor userInterruptPriority.

    session_:= process_ newDebugSessionNamed: 'test session' startedAt: context_.     session_ runToSelection: (Interval from: 28 to: 27) inContext: context_.
    self assert: ((session_ pcRangeForContext: context_) first == 3)`

cheers - Thomas


    Thomas



        - Replacing the stepOver with stepInto and removing the equal
        condition on contexts -> The RunToHere goes to the 3+3.
        Looking at the source code position of the program counter,
        it doesn't enter the block and seems to resolve it in a
        single step. I don't really get why that is, considering
        using the stepInto button of the debugger does enter the
        block. Here is the series of source code positions of the
        program counter during the RunToHere: (21 to: 22)(34 to:
        36)(34 to: 36)(49 to: 60)(38 to: 60)(38 to: 60)(65 to: 66).
        However, removing the equal condition on contexts means that
        if the method call returns before reaching the cursor, it
        won't stop!

        - An idea could be to have the RunToHere place a metalink on
        the selected node and let the execution run until it hits the
        metalink, which then updates the debugger. Potential problems
        are that it implies installing a metalink on a method that is
        already on the stack, which may not be that easy to do
        properly (in particular, it affects the program counter since
        it changes the bytecode), and there is the potential case
        where the metalink is never reached (for example imagine the
        myEvalBlock: method of my example is just storing the block
        and not evaluating it).


        Cheers,
        Thomas



        Le 09/11/2017 à 22:06, Stephane Ducasse a écrit :

            Agreed. Thomas? It would be a good bone to ... (Un bon os
            a ronger) .

            Stef

            On Thu, Nov 9, 2017 at 4:32 AM, Tudor Girba
            <[email protected] <mailto:[email protected]>> wrote:

                Hi,

                The basic tools, such as debugger, are expected to
                work. If something does not work, it’s a bug.

                Cheers,
                Doru


                    On Nov 8, 2017, at 11:59 PM, Tim Mackinnon
                    <[email protected]> <mailto:[email protected]> wrote:

                    I think it's broken in Pharo 6 too, as I often
                    find it unreliable.

                    It's hard to know what should work anymore - we
                    really need a stabilisation release to let the
                    dust settle.

                    I'm always a bit reticent to report things as I'm
                    not sure what you expect to work.

                    Tim

                    Sent from my iPhone

                        On 8 Nov 2017, at 20:40, Stephane Ducasse
                        <[email protected]
                        <mailto:[email protected]>> wrote:

                        Hi

                        I have the following method and I have my
                        cursor -MY CURSOR HERE-
                        I select the menu run to here and .... I exit
                        the method.
                        :(

                        Is run to here working in Pharo 70?
                        I start to get worry about the number of bugs
                        I get when using Pharo70.

                        Stef


                        fileOut
                        "File out the receiver, to a file whose name
                        is a function of the
                        change-set name and a unique numeric tag."

                        | nameToUse |
                        self halt.
                        self class
                        promptForDefaultChangeSetDirectoryIfNecessary.
                        nameToUse := (self defaultChangeSetDirectory
                        / self name , 'cs')
                        nextVersion basename.
                        UIManager default
                        showWaitCursorWhile:
                        [
                        | internalStream |
                        internalStream := (String new: 10000)
                        writeStream.

                        -MY CURSOR HERE-

                        internalStream
                        header;
                        timeStamp.
                        self fileOutPreambleOn: internalStream.
                        self fileOutOn: internalStream.
                        self fileOutPostscriptOn: internalStream.
                        CodeExporter
                        writeSourceCodeFrom: internalStream
                        baseName: (nameToUse copyFrom: 1 to:
                        nameToUse size - 3)
                        isSt: false ]


                --
                www.tudorgirba.com <http://www.tudorgirba.com>
                www.feenk.com <http://www.feenk.com>

                "Value is always contextual."











'From Pharo7.0alpha of 9 November 2017 [Build information: 
Pharo-7.0+alpha.build.278.sha.1f42562ef634508d48a1e41ebf06af09c873e029 (32 
Bit)] on 13 November 2017 at 4:13:44.337158 pm'!

!DebugSession methodsFor: 'debugging actions' stamp: 'ThomasDupriez 11/13/2017 
16:00'!
runToSelection: selectionInterval inContext: aContext
        "Attempt to step over instructions in selectedContext until the
        execution reaches the selected instruction. This happens when the
        program counter passes the begining of selectionInterval.

        A not nill and valid interval is expected."
        (self pcRangeForContext: aContext) first >= selectionInterval first
            ifTrue: [ ^self ].
        self stepOver: aContext.
        [ aContext == self interruptedContext and: [ (self pcRangeForContext: 
aContext) first < selectionInterval first ] ]
            whileTrue: [ self stepThrough: aContext ]! !
'From Pharo7.0alpha of 9 November 2017 [Build information: 
Pharo-7.0+alpha.build.278.sha.1f42562ef634508d48a1e41ebf06af09c873e029 (32 
Bit)] on 13 November 2017 at 4:08:01.157412 pm'!
Object subclass: #MyClass
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'MyPack'!

!MyClass methodsFor: 'as yet unclassified' stamp: 'ThomasDupriez 11/13/2017 
16:06'!
meth
        self halt.
        1+1.
        MyClass new evalBlock: [ 
                2+2.
        ].
        3+3.! !

!MyClass methodsFor: 'as yet unclassified' stamp: 'ThomasDupriez 11/13/2017 
16:07'!
callMeth
        self meth.! !


!MyClass methodsFor: 'instance creation' stamp: 'ThomasDupriez 11/13/2017 
13:32'!
evalBlock: aBlock
        aBlock value.! !

Reply via email to