[squeak-dev] strange bug

Ralph Boland rpboland at gmail.com
Tue Jul 28 20:55:07 UTC 2009


I have a strange but that I don't know what to do with.
Any suggestions on how to proceed most welcome.
The bug occurs when I stop after a halt during a printOn:
(The code prevents the halt occurring a second time to prevent
infinite recursion during printing.  I need to do this to track down
an unrelated bug in a different tree printing class than the one
described below.

I have some code that builds/stores a tree.
The tree is complicated and I need to be able to print the tree
different ways so the tree object has an instance variable "printer"
that stores an object that knows how to print the tree.
If no printer is stored then a default printer object is created
to print the tree.

The printOn:  method for my tree class is as follows:

printOn: aStream
		(printer)
	ifNil:		[HeapTreePrinterNumbered printTree: self on: aStream]
	ifNotNil:	[printer printOn: aStream].

Here's the printTree:on:  method:

printTree: heapTree on: aStream

			| aMe |
			
	aMe  := self new: heapTree.
	aMe printOn: aStream.

The printOn: method for  HeapTreePrinterNumbered is as follows:

printOn: aStream
	
			| a b |
			
	a := a.		"2 dummy statements to see if it had any affect. It didn't."
	b := b.
	stream := aStream.
	self chkHalt.				"halts first time through only"
	self printTree.
	stream := nil.

Based on the above code one would expect that it doesn't matter
whether my tree stores a  HeapTreePrinterNumbered object or nil
in its printer instance variable when I attempt to print my tree.
However, if I go the default printer route then my code works as
expected while if I install a  HeapTreePrinterNumbered object into
my tree odd things happen.

In the latter case, I get the halt caused by the  "self chkHalt"
invocation as expected.
But when I  run the code  "stream == aStream"   false is returned???????????
Note that the printOn:  is the only place where instance var  'stream'
is assigned.    In fact stream contains part or all of the data that
will be placed in it by the "self printTree"  code even though that code
hasn't been invoked yet!!!!
If I select  self from the debugger the tree is
displayed properly.  If I then select stream again nil is displayed.
(As it should because the printOn: has been invoked again which,
of course, set stream to nil as it last act. (after properly
displaying the tree))

If instead, after hitting the halt, I do a restart from the printOn:
and single step
through then the code  "stream := aStream" works as expected.

In instead, after hitting the halt, I do a continue I get the stack:


BlockContext>>cannotReturn:
[] in String class(SequenceableCollection
class)>>streamContents:limitedTo: {[^ stream contents]}
LimitedWriteStream>>nextPut:
LimitedWriteStream(WriteStream)>>cr
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
HeapTreePrinterNumbered(HeapTreePrinter)>>printTree
HeapTreePrinterNumbered(HeapTreePrinterAbstract)>>printOn:
CrossLinkedHeapTree>>printOn:
[] in CrossLinkedHeapTree(Object)>>printStringLimitedTo: {[:s | self
printOn: s]}
String class(SequenceableCollection class)>>streamContents:limitedTo:
CrossLinkedHeapTree(Object)>>printStringLimitedTo:
CrossLinkedHeapTree(Object)>>printString
TextMorphEditor(ParagraphEditor)>>printIt
[] in TextMorphEditor(ParagraphEditor)>>printIt: {[self printIt]}
TextMorphEditor(Controller)>>terminateAndInitializeAround:
TextMorphEditor(ParagraphEditor)>>printIt:
TextMorphEditor(ParagraphEditor)>>dispatchOnCharacter:with:
TextMorphEditor>>dispatchOnCharacter:with:
TextMorphEditor(ParagraphEditor)>>readKeyboard
TextMorphEditor>>readKeyboard
[] in TextMorphForEditView(TextMorph)>>keyStroke: {[editor readKeyboard]}
TextMorphForEditView(TextMorph)>>handleInteraction:fromEvent:
TextMorphForEditView>>handleInteraction:fromEvent:
TextMorphForEditView(TextMorph)>>keyStroke:
TextMorphForEditView>>keyStroke:
TextMorphForEditView(TextMorph)>>handleKeystroke:
KeyboardEvent>>sentTo:
TextMorphForEditView(Morph)>>handleEvent:
TextMorphForEditView(Morph)>>handleFocusEvent:
[] in HandMorph>>sendFocusEvent:to:clear: {[ActiveHand := self.
ActiveEvent := anEvent.  result := focusHolder     han...]}
[] in PasteUpMorph>>becomeActiveDuring: {[aBlock value]}
BlockContext>>on:do:
PasteUpMorph>>becomeActiveDuring:
HandMorph>>sendFocusEvent:to:clear:
HandMorph>>sendEvent:focus:clear:
HandMorph>>sendKeyboardEvent:
HandMorph>>handleEvent:
HandMorph>>processEvents
[] in WorldState>>doOneCycleNowFor: {[:h |  ActiveHand := h.  h
processEvents.  capturingGesture := capturingGest...]}
Array(SequenceableCollection)>>do:
WorldState>>handsDo:
WorldState>>doOneCycleNowFor:
WorldState>>doOneCycleFor:
PasteUpMorph>>doOneCycle
[] in Project class>>spawnNewProcess {[[World doOneCycle.  Processor
yield.  false] whileFalse.  nil]}
...etc...


Again,  any suggestions most welcome.

Ralph Boland



More information about the Squeak-dev mailing list