[squeak-dev] Re: MVC debugging
Florin Mateoc
fmateoc at gmail.com
Wed Sep 8 19:35:27 UTC 2010
On 9/8/2010 1:42 PM, David T. Lewis wrote:
> On Wed, Sep 08, 2010 at 12:11:45PM -0400, Florin Mateoc wrote:
>> On 9/8/2010 6:46 AM, David T. Lewis wrote:
>>> Florin, Andreas,
>>>
>>> Great thanks for this progress! I do get a debugger window now (yay!).
>>> I'm just heading out the door for the day but look forward to playing
>>> with this later.
>>>
>>> Dave
>>>
>> I made a little more progress:
>>
>> there is a bug in MVCToolBuilder class>>isActiveBuilder, which only responds true when asked from within the UI process.
>> Well, there are other processes in MVC as well, and the interrupt handling happens to be from a forked process. As a
>> result, ToolBuilder default is always nil in a non-UI process.
>> My tentative solution for this is, (but I don't know how this works with multiple projects, if supported):
>>
>> isActiveBuilder
>> "Answer whether I am the currently active builder"
>> "This is really a way of answering whether 'Smalltalk isMVC'"
>> ScheduledControllers ifNil:[^false].
>> ^(ScheduledControllers activeControllerProcess ifNil:[^false]) isTerminated not
>>
>>
>> I would also qualify as a semi-bug the fact that the Default class variable in ToolBuilder is unused. What looks like
>> lazy initialization in #isActiveBuilder never sets the variable. This was quite confusing and it threw me off track for
>> a while. If it is not used, (the setter is never called, at least not in the base image, not even indirectly through the
>> class pool, I checked :) ), it should be removed.
>>
> Yes the unused Default in ToolBuilder is a semi-bug. Possibly it should be
> set as a side effect of entering a project (Project>>enter:revert:saveForRevert:).
> I remember looking at this during the Project refactoring, but I thought at
> the time that it was safer to leave it alone (setting a global variable as
> a side effect of some other operation seemed dangerous, and the dynamic
> calculation seemed to be working fine as it was).
>
> Possibly a nicer approach would be to vector it through Project such that
> the current project always knows its ToolBuilder. But this adds Toolbuilder
> dependency in the System package, which did not seem like a good idea
> either.
>
> Dave
>
>
Finally! There were a couple of bugs in ControlManager>>interruptName:preemptedProcess: (e.g. Debugger does not
implement #controller)
I went ahead and simplified it a bit and spelled out the assumptions (as comments).
With this changeset the notifier now opens for the user interrupt, and you can also do "[1 halt] fork"
Florin
-------------- next part --------------
'From Squeak4.1 of 17 April 2010 [latest update: #9957] on 8 September 2010 at 3:30:48 pm'!
!ControlManager methodsFor: 'scheduling' stamp: 'fm 9/8/2010 15:29'!
interruptName: labelString preemptedProcess: theInterruptedProcess
"Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller."
"This method is assumed to be called from a non-UI process"
activeControllerProcess suspend.
activeController ~~ nil ifTrue: [
"Carefully de-emphasis the current window."
activeController view topView deEmphasizeForDebugger].
"This will just scheduleNoTerminate the newly built controller"
Debugger
openInterrupt: labelString
onProcess: activeControllerProcess.
self searchForActiveController! !
!Debugger methodsFor: 'initialize' stamp: 'fm 9/8/2010 01:42'!
openFullNoSuspendLabel: aString
"Create and schedule a full debugger with the given label. Do not terminate the current active process."
| oldContextStackIndex |
oldContextStackIndex := contextStackIndex.
self expandStack. "Sets contextStackIndex to zero."
ToolBuilder open1: self label: aString.
self toggleContextStackIndex: oldContextStackIndex.! !
!Debugger methodsFor: 'initialize' stamp: 'fm 9/8/2010 15:16'!
openNotifierContents: msgString label: label
"Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired."
"NOTE: When this method returns, a new process has been scheduled to run the windows, and thus this notifier, but the previous active porcess has not been suspended. The sender will do this."
| msg builder spec |
Sensor flushKeyboard.
savedCursor := Sensor currentCursor.
Sensor currentCursor: Cursor normal.
(label beginsWith: 'Space is low')
ifTrue: [msg := self lowSpaceChoices, (msgString ifNil: [''])]
ifFalse: [msg := msgString].
builder := ToolBuilder default.
spec := self buildNotifierWith: builder label: label message: msg.
self expandStack.
builder open1: spec.
errorWasInUIProcess := Project spawnNewProcessIfThisIsUI: interruptedProcess.
! !
!Debugger class methodsFor: 'opening' stamp: 'fm 9/8/2010 02:02'!
openOn: process context: context label: title contents: contentsStringOrNil fullView: bool
"Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger."
| controller errorWasInUIProcess debugger |
Smalltalk isMorphic
ifTrue: [errorWasInUIProcess := Project spawnNewProcessIfThisIsUI: process]
ifFalse: [controller := ScheduledControllers activeControllerProcess == process
ifTrue: [ScheduledControllers activeController].
debugger := self new process: process controller: controller context: context.
bool
ifTrue: [debugger openFullNoSuspendLabel: title]
ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]].
WorldState addDeferredUIMessage: [
[
debugger := self new process: process controller: controller context: context.
Smalltalk isMorphic
ifTrue: ["schedule debugger in deferred UI message to address redraw
problems after opening a debugger e.g. from the testrunner."
"WorldState addDeferredUIMessage: "
bool
ifTrue: [debugger openFullNoSuspendLabel: title]
ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]]
ifFalse: ["deferred UI message would require special controller in MVC"
bool
ifTrue: [debugger openFullNoSuspendLabel: title]
ifFalse: [debugger openNotifierContents: contentsStringOrNil label: title]].
debugger errorWasInUIProcess: errorWasInUIProcess.
Preferences logDebuggerStackToFile ifTrue: [
Smalltalk logError: title inContext: context to: 'SqueakDebug.log'].
Smalltalk isMorphic
ifFalse: [ScheduledControllers searchForActiveController "needed since openNoTerminate (see debugger #open...) does not set up activeControllerProcess if activeProcess (this fork) is not the current activeControllerProcess (see #scheduled:from:)"].
] on: Error do: [:ex |
self primitiveError:
'Orginal error: ',
title asString, '.
Debugger error: ',
([ex description] on: Error do: ['a ', ex class printString]), ':'
]
].
process suspend.
! !
!MVCToolBuilder methodsFor: 'opening' stamp: 'fm 9/8/2010 15:23'!
open1: anObject
"Build and open the object. Answer the widget opened."
| window |
window := self build: anObject.
window controller openNoTerminate.
^window! !
!MVCToolBuilder methodsFor: 'opening' stamp: 'fm 9/8/2010 01:41'!
open1: anObject label: aString
"Build an open the object, labeling it appropriately. Answer the widget opened."
| window |
window := self build: anObject.
window label: aString.
window controller openNoTerminate.
^window! !
!MorphicToolBuilder methodsFor: 'opening' stamp: 'fm 9/8/2010 01:39'!
open1: anObject
"Build and open the object. Answer the widget opened."
| morph |
anObject isMorph
ifTrue:[morph := anObject]
ifFalse:[morph := self build: anObject].
(morph isKindOf: MenuMorph)
ifTrue:[morph popUpInWorld: World].
(morph isKindOf: SystemWindow)
ifTrue:[morph openInWorldExtent: morph extent]
ifFalse:[morph openInWorld].
^morph! !
!MorphicToolBuilder methodsFor: 'opening' stamp: 'fm 9/8/2010 01:41'!
open1: anObject label: aString
"Build an open the object, labeling it appropriately. Answer the widget opened."
| window |
window := self open: anObject.
window setLabel: aString.
^window! !
!ToolBuilder class methodsFor: 'instance creation' stamp: 'fm 9/8/2010 02:10'!
open1: aClass label: aString
^self default open1: aClass label: aString! !
!MVCToolBuilder class methodsFor: 'accessing' stamp: 'fm 9/8/2010 11:52'!
isActiveBuilder
"Answer whether I am the currently active builder"
"This is really a way of answering whether 'Smalltalk isMVC'"
ScheduledControllers ifNil:[^false].
^(ScheduledControllers activeControllerProcess ifNil:[^false]) isTerminated not! !
More information about the Squeak-dev
mailing list
|