Exceptions in HoverHelp

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

Exceptions in HoverHelp

Terry Raymond

Sometimes we get the following exception with the hover help.

It would appear to me that there is a race condition. The use of global variables with multiple processes is asking for trouble.

 

 

UndefinedObject(Object)>>doesNotUnderstand:

 

SOURCE CODE:

doesNotUnderstand: aMessage

                "The default behavior is to create a Notifier containing the

                appropriate message and to allow the user to open a Debugger.

                Subclasses can override this message in order to modify this behavior."

 

                | excpt resumeValue |

 

">>> Miosoft 2007.11.27 - deal with removal of the method Object>>value.  Note that adding an implementation of Object>>value that conditionally fails doesn't work, since MenuItem>>rawLabel (at least) tests 'label respondsTo: #value' and will convert almost all system menu labels into 'UserMessage'."

                aMessage selector = #value ifTrue: [

                                "Dance around potential problems with a partially loaded system."

                                #{Miosoft.MiosoftVersionInformation} ifDefinedDo: [:v |

                                                ((v respondsTo: #isDevelopment) and: [v isDevelopment == true]) ifFalse: [

                                                                "Not in development.  Just pretend Object>>value was ^self."

                                                                ^self]]].

"<<<"

 

                excpt := Object messageNotUnderstoodSignal newException.

                excpt

                                searchFrom: thisContext;

                                parameter: aMessage;

                                messageText: [| selectorString |

                                                selectorString :=

                                                                [aMessage selector printString]

                                                                                on: Error

                                                                                do: [:ex |

                                                                                                ex return:

                                                                                                                (#errSelectorNotPrintable << #dialogs >> '** unprintable selector **')

                                                                                                                expandMacros asString].

                                                (#errNotUnderstood << #dialogs >> 'Message not understood: <1s>')

                                                                expandMacrosWith: selectorString];

                                originator: self;

                                makeSureResumable.

                resumeValue := excpt >>>>>raiseSignal<<<<<.

                ^excpt reachedDefaultHandler

                                ifTrue: [self perform: aMessage selector withArguments: aMessage arguments]

                                ifFalse: [resumeValue]

 

                "3 zork."

 

PARMS AND TEMP VARS:

                aMessage = a Message with selector: #displayBoxFor: and arguments: #(a GraphicPart)

                excpt = a MessageNotUnderstood (originator = UndefinedObject): Message not understood: #displayBoxFor:

                resumeValue = nil

 

INST VARS IN RECEIVER (nil):

=========================================================

optimized [] in HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant >>>>>displayBoxFor: component<<<<<).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]

 

PARMS AND TEMP VARS:

   self = a HoverHelpWindow 6301

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpWindow>>openTooltip:):

                method = CompiledBlock [] in HoverHelpWindow>>openTooltip:

                outerContext = nil

                copiedValues = #(a HoverHelpWindow 6301 a VisualBlock)

=========================================================

optimized [] in RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock >>>>>value<<<<<.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]

 

PARMS AND TEMP VARS:

                result = nil

                activeProcess = a Process in Process>>resume

   self = a RecursionLock

                recover = true

                priority = 50

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

BlockClosure>>ifCurtailed:

 

SOURCE CODE:

ifCurtailed: terminationBlock

                "Evaluate the receiver and return its result. If abnormal termination of the receiver occurs, terminationBlock

                is evaluated. The value returned from the evaluation of terminationBlock is discarded."

 

                <exception: #unwind>

 

                ^self >>>>>value<<<<<

 

PARMS AND TEMP VARS:

                terminationBlock = BlockClosure [] in RecursionLock>>critical:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock value.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] >>>>>ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

                recover = true

                activeProcess = a Process in Process>>resume

                priority = 50

 

INST VARS IN RECEIVER (a RecursionLock):

                owner = a Process in Process>>resume

                semaphore = Semaphore () [0]

=========================================================

HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock >>>>>critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant displayBoxFor: component).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]<<<<<

 

PARMS AND TEMP VARS:

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (a HoverHelpWindow 6301):

                handle = GraphicsHandle from:#[157 24 0 0 28 22 69 2 0 0 0 0 0 0 0 0 0 0 8 0](6301)

                width = 202

                height = 18

                background = ColorValue white

                inputOrigin = 307 @ 459

                creationOrigin = 307 @ 459

                sensor = an EventSensor

                iconic = false

                windowType = #popUp

                effectiveWindowType = nil

                statusLineHeight = 0

                allowsStatusLine = true

                mapped = false

                eventHandlers = nil

                windowManager = a NullWindowManager

                component = a GraphicPart

                paintPreferences = nil

                controller = nil

                masterWindow = nil

                lock = a RecursionLock

=========================================================

HoverHelpWindow class>>openTooltip:for:

 

SOURCE CODE:

openTooltip: aTooltipGraphic for: requestingView

                "Open a tooltip with location relative to the current mouse position."

 

                self targetView: requestingView.

                ^self current >>>>>openTooltip: aTooltipGraphic<<<<<

 

PARMS AND TEMP VARS:

                aTooltipGraphic = a VisualBlock

                requestingView = a Miosoft.HierarchyView

 

INST VARS IN RECEIVER (HoverHelpWindow):

                superclass = TransientWindow

                methodDict = MethodDictionary (#initialize #close #open #label #canProcessEvent #lock: #eventConsumer #tooltipAssistant #lock #isInvalid #recycle #openTooltip: #targetView )

                format = 16404

                subclasses = nil

                instanceVariables = #('lock')

                organization = $$-1-$$

                name = #HoverHelpWindow

                classPool = HoverHelpWindow asNameSpace

                environment = UI

                current = a HoverHelpWindow 6301

                targetView = a Miosoft.HierarchyView

                lastCloseTime = 3527243018921

=========================================================

optimized [] in HoverHelpAssistant>>openTooltip

 

SOURCE CODE:

openTooltip

 

                self tooltipGraphic

                                ifNotNil: [:tip | self windowClass >>>>>openTooltip: tip for: view<<<<<]

 

PARMS AND TEMP VARS:

                tip = a VisualBlock

   self = a TooltipAssistant

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

BlockClosure>>cull:

 

SOURCE CODE:

cull: anObject

                "If the receiver can handle an argument, evaluate with the argument, otherwise drop the last argument and evaluate as a no arg block."

 

                ^self numArgs = 0

                                ifTrue: [self value]

                                ifFalse: [self >>>>>value: anObject<<<<<]

 

PARMS AND TEMP VARS:

                anObject = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

VisualBlock(Object)>>ifNotNil:

 

SOURCE CODE:

ifNotNil: aBlock

                "If the receiver is not nil, answer the evaluation of aBlock (with the receiver as

                its argument if it takes one), otherwise answer nil.  Since the receiver is not nil,

                answer aBlock's evaluation.  Passing the receiver to aBlock is handy for idioms

                such as

                                self toolBarSpec ifNotNil: [:spec | ...].

                UndefinedObject reimplements this to not evaluate aBlock."

 

                ^aBlock >>>>>cull: self<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpAssistant>>openTooltip

 

INST VARS IN RECEIVER (a VisualBlock):

                block = BlockClosure [] in ComposedText>>asTooltipGraphicFor:

                bounds = 0 @ 0 corner: 179 @ 18

                paint = ColorValue black

=========================================================

 

Terry

 

===========================================================

Terry Raymond

Crafted Smalltalk

80 Lazywood Ln.

Tiverton, RI  02878

(401) 624-4517      [hidden email]

===========================================================

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Exceptions in HoverHelp

Karsten Kusche
Hi Terry,

please look for senders of #tooltip:. since 7.9 you may only call this method once. If you send it too often in a too short period of time, the help system breaks. Instead of sending #tooltip: you may use a block with the actual value and then the block will be evaluated everytime the tooltip is requested.

Kind Regards
Karsten

-- 
Karsten Kusche - Dipl. Inf. - [hidden email]
Georg Heeg eK - Köthen
Handelsregister: Amtsgericht Dortmund A 12812 

Am Dienstag, 9. Oktober 2012 um 16:28 schrieb Terry Raymond:

Sometimes we get the following exception with the hover help.

It would appear to me that there is a race condition. The use of global variables with multiple processes is asking for trouble.

 

 

UndefinedObject(Object)>>doesNotUnderstand:

 

SOURCE CODE:

doesNotUnderstand: aMessage

                "The default behavior is to create a Notifier containing the

                appropriate message and to allow the user to open a Debugger.

                Subclasses can override this message in order to modify this behavior."

 

                | excpt resumeValue |

 

">>> Miosoft 2007.11.27 - deal with removal of the method Object>>value.  Note that adding an implementation of Object>>value that conditionally fails doesn't work, since MenuItem>>rawLabel (at least) tests 'label respondsTo: #value' and will convert almost all system menu labels into 'UserMessage'."

                aMessage selector = #value ifTrue: [

                                "Dance around potential problems with a partially loaded system."

                                #{Miosoft.MiosoftVersionInformation} ifDefinedDo: [:v |

                                                ((v respondsTo: #isDevelopment) and: [v isDevelopment == true]) ifFalse: [

                                                                "Not in development.  Just pretend Object>>value was ^self."

                                                                ^self]]].

"<<<"

 

                excpt := Object messageNotUnderstoodSignal newException.

                excpt

                                searchFrom: thisContext;

                                parameter: aMessage;

                                messageText: [| selectorString |

                                                selectorString :=

                                                                [aMessage selector printString]

                                                                                on: Error

                                                                                do: [:ex |

                                                                                                ex return:

                                                                                                                (#errSelectorNotPrintable << #dialogs >> '** unprintable selector **')

                                                                                                                expandMacros asString].

                                                (#errNotUnderstood << #dialogs >> 'Message not understood: <1s>')

                                                                expandMacrosWith: selectorString];

                                originator: self;

                                makeSureResumable.

                resumeValue := excpt >>>>>raiseSignal<<<<<.

                ^excpt reachedDefaultHandler

                                ifTrue: [self perform: aMessage selector withArguments: aMessage arguments]

                                ifFalse: [resumeValue]

 

                "3 zork."

 

PARMS AND TEMP VARS:

                aMessage = a Message with selector: #displayBoxFor: and arguments: #(a GraphicPart)

                excpt = a MessageNotUnderstood (originator = UndefinedObject): Message not understood: #displayBoxFor:

                resumeValue = nil

 

INST VARS IN RECEIVER (nil):

=========================================================

optimized [] in HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant >>>>>displayBoxFor: component<<<<<).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]

 

PARMS AND TEMP VARS:

   self = a HoverHelpWindow 6301

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpWindow>>openTooltip:):

                method = CompiledBlock [] in HoverHelpWindow>>openTooltip:

                outerContext = nil

                copiedValues = #(a HoverHelpWindow 6301 a VisualBlock)

=========================================================

optimized [] in RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock >>>>>value<<<<<.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]

 

PARMS AND TEMP VARS:

                result = nil

                activeProcess = a Process in Process>>resume

   self = a RecursionLock

                recover = true

                priority = 50

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

BlockClosure>>ifCurtailed:

 

SOURCE CODE:

ifCurtailed: terminationBlock

                "Evaluate the receiver and return its result. If abnormal termination of the receiver occurs, terminationBlock

                is evaluated. The value returned from the evaluation of terminationBlock is discarded."

 

                <exception: #unwind>

 

                ^self >>>>>value<<<<<

 

PARMS AND TEMP VARS:

                terminationBlock = BlockClosure [] in RecursionLock>>critical:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock value.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] >>>>>ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

                recover = true

                activeProcess = a Process in Process>>resume

                priority = 50

 

INST VARS IN RECEIVER (a RecursionLock):

                owner = a Process in Process>>resume

                semaphore = Semaphore () [0]

=========================================================

HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock >>>>>critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant displayBoxFor: component).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]<<<<<

 

PARMS AND TEMP VARS:

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (a HoverHelpWindow 6301):

                handle = GraphicsHandle from:#[157 24 0 0 28 22 69 2 0 0 0 0 0 0 0 0 0 0 8 0](6301)

                width = 202

                height = 18

                background = ColorValue white

                inputOrigin = 307 @ 459

                creationOrigin = 307 @ 459

                sensor = an EventSensor

                iconic = false

                windowType = #popUp

                effectiveWindowType = nil

                statusLineHeight = 0

                allowsStatusLine = true

                mapped = false

                eventHandlers = nil

                windowManager = a NullWindowManager

                component = a GraphicPart

                paintPreferences = nil

                controller = nil

                masterWindow = nil

                lock = a RecursionLock

=========================================================

HoverHelpWindow class>>openTooltip:for:

 

SOURCE CODE:

openTooltip: aTooltipGraphic for: requestingView

                "Open a tooltip with location relative to the current mouse position."

 

                self targetView: requestingView.

                ^self current >>>>>openTooltip: aTooltipGraphic<<<<<

 

PARMS AND TEMP VARS:

                aTooltipGraphic = a VisualBlock

                requestingView = a Miosoft.HierarchyView

 

INST VARS IN RECEIVER (HoverHelpWindow):

                superclass = TransientWindow

                methodDict = MethodDictionary (#initialize #close #open #label #canProcessEvent #lock: #eventConsumer #tooltipAssistant #lock #isInvalid #recycle #openTooltip: #targetView )

                format = 16404

                subclasses = nil

                instanceVariables = #('lock')

                organization = $$-1-$$

                name = #HoverHelpWindow

                classPool = HoverHelpWindow asNameSpace

                environment = UI

                current = a HoverHelpWindow 6301

                targetView = a Miosoft.HierarchyView

                lastCloseTime = 3527243018921

=========================================================

optimized [] in HoverHelpAssistant>>openTooltip

 

SOURCE CODE:

openTooltip

 

                self tooltipGraphic

                                ifNotNil: [:tip | self windowClass >>>>>openTooltip: tip for: view<<<<<]

 

PARMS AND TEMP VARS:

                tip = a VisualBlock

   self = a TooltipAssistant

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

BlockClosure>>cull:

 

SOURCE CODE:

cull: anObject

                "If the receiver can handle an argument, evaluate with the argument, otherwise drop the last argument and evaluate as a no arg block."

 

                ^self numArgs = 0

                                ifTrue: [self value]

                                ifFalse: [self >>>>>value: anObject<<<<<]

 

PARMS AND TEMP VARS:

                anObject = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

VisualBlock(Object)>>ifNotNil:

 

SOURCE CODE:

ifNotNil: aBlock

                "If the receiver is not nil, answer the evaluation of aBlock (with the receiver as

                its argument if it takes one), otherwise answer nil.  Since the receiver is not nil,

                answer aBlock's evaluation.  Passing the receiver to aBlock is handy for idioms

                such as

                                self toolBarSpec ifNotNil: [:spec | ...].

                UndefinedObject reimplements this to not evaluate aBlock."

 

                ^aBlock >>>>>cull: self<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpAssistant>>openTooltip

 

INST VARS IN RECEIVER (a VisualBlock):

                block = BlockClosure [] in ComposedText>>asTooltipGraphicFor:

                bounds = 0 @ 0 corner: 179 @ 18

                paint = ColorValue black

=========================================================

 

Terry

 

===========================================================

Terry Raymond

Crafted Smalltalk

80 Lazywood Ln.

Tiverton, RI  02878

(401) 624-4517      [hidden email]

===========================================================

 

_______________________________________________
vwnc mailing list


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Exceptions in HoverHelp

Terry Raymond

Karsten

 

You made my point about using a globals and multiple processes.

Actually, the problem occurs in a view with no special tool tip being used.

Just simply move the cursor over the various widgets and eventually the exception

occurs.

 

Terry

 

===========================================================

Terry Raymond

Crafted Smalltalk

80 Lazywood Ln.

Tiverton, RI  02878

(401) 624-4517      [hidden email]

===========================================================

 

From: Karsten Kusche [mailto:[hidden email]]
Sent: Tuesday, October 09, 2012 10:36 AM
To: Terry Raymond
Cc: VWNC
Subject: Re: [vwnc] Exceptions in HoverHelp

 

Hi Terry,

 

please look for senders of #tooltip:. since 7.9 you may only call this method once. If you send it too often in a too short period of time, the help system breaks. Instead of sending #tooltip: you may use a block with the actual value and then the block will be evaluated everytime the tooltip is requested.

 

Kind Regards

Karsten

 

-- 

Karsten Kusche - Dipl. Inf. - [hidden email]

Georg Heeg eK - Köthen

Handelsregister: Amtsgericht Dortmund A 12812 

 

Am Dienstag, 9. Oktober 2012 um 16:28 schrieb Terry Raymond:

Sometimes we get the following exception with the hover help.

It would appear to me that there is a race condition. The use of global variables with multiple processes is asking for trouble.

 

 

UndefinedObject(Object)>>doesNotUnderstand:

 

SOURCE CODE:

doesNotUnderstand: aMessage

                "The default behavior is to create a Notifier containing the

                appropriate message and to allow the user to open a Debugger.

                Subclasses can override this message in order to modify this behavior."

 

                | excpt resumeValue |

 

">>> Miosoft 2007.11.27 - deal with removal of the method Object>>value.  Note that adding an implementation of Object>>value that conditionally fails doesn't work, since MenuItem>>rawLabel (at least) tests 'label respondsTo: #value' and will convert almost all system menu labels into 'UserMessage'."

                aMessage selector = #value ifTrue: [

                                "Dance around potential problems with a partially loaded system."

                                #{Miosoft.MiosoftVersionInformation} ifDefinedDo: [:v |

                                                ((v respondsTo: #isDevelopment) and: [v isDevelopment == true]) ifFalse: [

                                                                "Not in development.  Just pretend Object>>value was ^self."

                                                                ^self]]].

"<<<"

 

                excpt := Object messageNotUnderstoodSignal newException.

                excpt

                                searchFrom: thisContext;

                                parameter: aMessage;

                                messageText: [| selectorString |

                                                selectorString :=

                                                                [aMessage selector printString]

                                                                                on: Error

                                                                                do: [:ex |

                                                                                                ex return:

                                                                                                                (#errSelectorNotPrintable << #dialogs >> '** unprintable selector **')

                                                                                                                expandMacros asString].

                                                (#errNotUnderstood << #dialogs >> 'Message not understood: <1s>')

                                                                expandMacrosWith: selectorString];

                                originator: self;

                                makeSureResumable.

                resumeValue := excpt >>>>>raiseSignal<<<<<.

                ^excpt reachedDefaultHandler

                                ifTrue: [self perform: aMessage selector withArguments: aMessage arguments]

                                ifFalse: [resumeValue]

 

                "3 zork."

 

PARMS AND TEMP VARS:

                aMessage = a Message with selector: #displayBoxFor: and arguments: #(a GraphicPart)

                excpt = a MessageNotUnderstood (originator = UndefinedObject): Message not understood: #displayBoxFor:

                resumeValue = nil

 

INST VARS IN RECEIVER (nil):

=========================================================

optimized [] in HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant >>>>>displayBoxFor: component<<<<<).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]

 

PARMS AND TEMP VARS:

   self = a HoverHelpWindow 6301

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpWindow>>openTooltip:):

                method = CompiledBlock [] in HoverHelpWindow>>openTooltip:

                outerContext = nil

                copiedValues = #(a HoverHelpWindow 6301 a VisualBlock)

=========================================================

optimized [] in RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock >>>>>value<<<<<.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]

 

PARMS AND TEMP VARS:

                result = nil

                activeProcess = a Process in Process>>resume

   self = a RecursionLock

                recover = true

                priority = 50

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

BlockClosure>>ifCurtailed:

 

SOURCE CODE:

ifCurtailed: terminationBlock

                "Evaluate the receiver and return its result. If abnormal termination of the receiver occurs, terminationBlock

                is evaluated. The value returned from the evaluation of terminationBlock is discarded."

 

                <exception: #unwind>

 

                ^self >>>>>value<<<<<

 

PARMS AND TEMP VARS:

                terminationBlock = BlockClosure [] in RecursionLock>>critical:

 

INST VARS IN RECEIVER (BlockClosure [] in RecursionLock>>critical:):

                method = CompiledBlock [] in RecursionLock>>critical:

                outerContext = nil

                copiedValues = #(a Process in Process>>resume a RecursionLock #(true) 50 BlockClosure [] in HoverHelpWindow>>openTooltip:)

=========================================================

RecursionLock>>critical:

 

SOURCE CODE:

critical: aBlock

                "Evaluate aBlock only if the resource represented by the receiver is not

                already in use by another Process. If it is, wait on the receiver's semaphore

                until the resource is available. If the resource is already in use by the

                current process, execution may proceed. Answer the result of evaluating

                the block"

 

                "Miosoft July 29, 2004:  Rewritten to close failure window for externally terminated processes."

 

                | activeProcess recover priority |

                activeProcess := Processor activeProcess.

                activeProcess == owner ifTrue: [^aBlock value].

                priority := activeProcess priority.

                recover := false.

                ^[

                                | result |

                                activeProcess priority: 100.

                                semaphore waitIfCurtailedSignal.

                                recover := true.

                                owner := activeProcess.

                                activeProcess priority: priority.

 

                                result := aBlock value.

 

                                activeProcess priority: 100.

                                recover := false.

                                owner := nil.

                                semaphore signal.

                                activeProcess priority: priority.

 

                                result

                ] >>>>>ifCurtailed: [

                                activeProcess priority: 100.

                                recover ifTrue: [

                                                recover := false.

                                                owner := nil.

                                                semaphore signal].

                                activeProcess priority: priority]<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpWindow>>openTooltip:

                recover = true

                activeProcess = a Process in Process>>resume

                priority = 50

 

INST VARS IN RECEIVER (a RecursionLock):

                owner = a Process in Process>>resume

                semaphore = Semaphore () [0]

=========================================================

HoverHelpWindow>>openTooltip:

 

SOURCE CODE:

openTooltip: aVisualGraphic

                "Defer to the tooltipAssistant for the displayBox bounds.  The assistant may have its own ideas about the size and location of the displayBox, and may choose to ignore the component's bounds."

 

                self lock >>>>>critical:

                                                [self

                                                                component: aVisualGraphic asVisualPart;

                                                                displayBox: (self tooltipAssistant displayBoxFor: component).

                                                "After the window bounds is established with #displayBox:, reset the component bounds."

                                                component bounds: self bounds.

                                                self open]<<<<<

 

PARMS AND TEMP VARS:

                aVisualGraphic = a VisualBlock

 

INST VARS IN RECEIVER (a HoverHelpWindow 6301):

                handle = GraphicsHandle from:#[157 24 0 0 28 22 69 2 0 0 0 0 0 0 0 0 0 0 8 0](6301)

                width = 202

                height = 18

                background = ColorValue white

                inputOrigin = 307 @ 459

                creationOrigin = 307 @ 459

                sensor = an EventSensor

                iconic = false

                windowType = #popUp

                effectiveWindowType = nil

                statusLineHeight = 0

                allowsStatusLine = true

                mapped = false

                eventHandlers = nil

                windowManager = a NullWindowManager

                component = a GraphicPart

                paintPreferences = nil

                controller = nil

                masterWindow = nil

                lock = a RecursionLock

=========================================================

HoverHelpWindow class>>openTooltip:for:

 

SOURCE CODE:

openTooltip: aTooltipGraphic for: requestingView

                "Open a tooltip with location relative to the current mouse position."

 

                self targetView: requestingView.

                ^self current >>>>>openTooltip: aTooltipGraphic<<<<<

 

PARMS AND TEMP VARS:

                aTooltipGraphic = a VisualBlock

                requestingView = a Miosoft.HierarchyView

 

INST VARS IN RECEIVER (HoverHelpWindow):

                superclass = TransientWindow

                methodDict = MethodDictionary (#initialize #close #open #label #canProcessEvent #lock: #eventConsumer #tooltipAssistant #lock #isInvalid #recycle #openTooltip: #targetView )

                format = 16404

                subclasses = nil

                instanceVariables = #('lock')

                organization = $$-1-$$

                name = #HoverHelpWindow

                classPool = HoverHelpWindow asNameSpace

                environment = UI

                current = a HoverHelpWindow 6301

                targetView = a Miosoft.HierarchyView

                lastCloseTime = 3527243018921

=========================================================

optimized [] in HoverHelpAssistant>>openTooltip

 

SOURCE CODE:

openTooltip

 

                self tooltipGraphic

                                ifNotNil: [:tip | self windowClass >>>>>openTooltip: tip for: view<<<<<]

 

PARMS AND TEMP VARS:

                tip = a VisualBlock

   self = a TooltipAssistant

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

BlockClosure>>cull:

 

SOURCE CODE:

cull: anObject

                "If the receiver can handle an argument, evaluate with the argument, otherwise drop the last argument and evaluate as a no arg block."

 

                ^self numArgs = 0

                                ifTrue: [self value]

                                ifFalse: [self >>>>>value: anObject<<<<<]

 

PARMS AND TEMP VARS:

                anObject = a VisualBlock

 

INST VARS IN RECEIVER (BlockClosure [] in HoverHelpAssistant>>openTooltip):

                method = CompiledBlock [] in HoverHelpAssistant>>openTooltip

                outerContext = nil

                copiedValues = a TooltipAssistant

=========================================================

VisualBlock(Object)>>ifNotNil:

 

SOURCE CODE:

ifNotNil: aBlock

                "If the receiver is not nil, answer the evaluation of aBlock (with the receiver as

                its argument if it takes one), otherwise answer nil.  Since the receiver is not nil,

                answer aBlock's evaluation.  Passing the receiver to aBlock is handy for idioms

                such as

                                self toolBarSpec ifNotNil: [:spec | ...].

                UndefinedObject reimplements this to not evaluate aBlock."

 

                ^aBlock >>>>>cull: self<<<<<

 

PARMS AND TEMP VARS:

                aBlock = BlockClosure [] in HoverHelpAssistant>>openTooltip

 

INST VARS IN RECEIVER (a VisualBlock):

                block = BlockClosure [] in ComposedText>>asTooltipGraphicFor:

                bounds = 0 @ 0 corner: 179 @ 18

                paint = ColorValue black

=========================================================

 

Terry

 

===========================================================

Terry Raymond

Crafted Smalltalk

80 Lazywood Ln.

Tiverton, RI  02878

(401) 624-4517      [hidden email]

===========================================================

 

_______________________________________________

vwnc mailing list

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc