[squeak-dev] The Inbox: Tools-lrnp.1147.mcz

commits at source.squeak.org commits at source.squeak.org
Sat Apr 23 21:36:35 UTC 2022

A new version of Tools was added to project The Inbox:

==================== Summary ====================

Name: Tools-lrnp.1147
Author: lrnp
Time: 23 April 2022, 3:35:52.83495 pm
UUID: 343ce1d0-c9d3-47ec-8648-93be4d21471c
Ancestors: Tools-tpr.1146, Tools.lrnp-squeak5.3-debuggerFloodPrevention-20220423.6

debugger window flooding protection

Prevent the debugger from grinding the image to a halt by opening an endless torrent of windows. When a (by default) 6th debugger window would be opened within 3 seconds of opening the previous 5, the project is immediately suspended and exited so the user can attempt recovery or generate a debug log.

Comes with a preference to change the rate limit.

=============== Diff against Tools-tpr.1146 ===============

Item was changed:
  CodeHolder subclass: #Debugger
  	instanceVariableNames: 'interruptedProcess contextStack contextStackIndex contextStackList receiverInspector receiverInspectorState contextVariablesInspector contextVariablesInspectorState externalInterrupt proceedValue selectingPC savedCursor isolationHead failedProject labelString message untilExpression'
+ 	classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess MaximumOpenDebuggers NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
- 	classVariableNames: 'ContextStackKeystrokes ErrorReportServer FullStackSize InterruptUIProcessIfBlockedOnErrorInBackgroundProcess NotifierStackSize SavedExtent StackSizeLimit WantsAnnotationPane'
  	poolDictionaries: ''
  	category: 'Tools-Debugger'!
+ Debugger class
+ 	instanceVariableNames: 'openInstances'!
  !Debugger commentStamp: 'mt 12/17/2019 12:19' prior: 0!
  I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. The debugger is typically viewed through a window that views the stack of suspended contexts, the code for, and execution point in, the currently selected message, and inspectors on both the receiver of the currently selected message, and the variables in the current context.
  Special note on recursive errors:
  Some errors affect Squeak's ability to present a debugger.  This is normally an unrecoverable situation.  However, if such an error occurs in an isolation layer, Squeak will attempt to exit from the isolation layer and then present a debugger.  Here is the chain of events in such a recovery.
  	* A recursive error is detected.
  	* The current project is queried for an isolationHead
  	* Changes in the isolationHead are revoked
  	* The parent project of isolated project is returned to
  	* The debugger is opened there and execution resumes.
  If the user closes that debugger, execution continues in the outer project and layer.  If, after repairing some damage, the user proceeds from the debugger, then the isolationHead is re-invoked, the failed project is re-entered, and execution resumes in that world. 
  In September 2019, we added MorphicDebugger and MVCDebugger to untangle framework-specific features in our debugger infrastructure. However, this is just an intermediate step. The overall goal would be to remove those two subclasses again while preserving their functionality. Mostly, MVC and Morphic differ in their GUI-process management. This means that "proceed" and "close" work differently depending on the process that is being debugged. --- One idea is to attach that framework-specific information to the process objects. See Process >> #environmentAt: and #environmentAt:put:. Also see ToolSet's #handle* and #debug* methods.!
+ Debugger class
+ 	instanceVariableNames: 'openInstances'!

Item was added:
+ ----- Method: Debugger class>>checkDebuggerFlood (in category 'opening') -----
+ checkDebuggerFlood
+ 	"See if I am trying to open many debugger windows very quickly.
+ 	When flooding is detected the current project is suspended so the user can attempt to recover their image. See #recursiveError:."
+ 	openInstances ifNil: [openInstances := 0].
+ 	openInstances <= self maximumOpenDebuggers
+ 		ifTrue: [|proc|
+ 			openInstances := openInstances + 1.
+ 			proc := nil.
+ 			proc := [
+ 				(Delay forSeconds: 3) wait.
+ 				openInstances := openInstances - 1 max: 0.
+ 				proc terminate] newProcess.
+ 			proc priority: Processor lowIOPriority.
+ 			proc resume.
+ 			Processor yield]
+ 		ifFalse: [openInstances := 0. Project current recursiveError: 'Debugger Flooding Detected']!

Item was changed:
  ----- Method: Debugger class>>initialize (in category 'class initialization') -----
  	ContextStackKeystrokes := Dictionary new
  		at: $e put: #send;
  		at: $t put: #doStep;
  		at: $T put: #stepIntoBlock;
  		at: $p put: #proceed;
  		at: $r put: #restart;
  		at: $f put: #fullStack;
  		at: $w put: #where;
+ 	SavedExtent := self new initialExtent.
+ 	openInstances := 0.
- 	SavedExtent := self new initialExtent
  	"Debugger initialize"!

Item was added:
+ ----- Method: Debugger class>>maximumOpenDebuggers (in category 'preferences') -----
+ maximumOpenDebuggers
+ 	<preference: 'Maximum open debuggers'
+ 		category: 'debug'
+ 		description: 'Limit the number of debugger windows that can be opened within a 3 second sliding window. When the limit is reached the current project will be exited to either MVC (if in Morphic) or Morphic (if in MVC).
+ Recommended minimum is 5, also the default.'
+ 		type: #Integer>
+ 	^MaximumOpenDebuggers ifNil: [5]!

Item was added:
+ ----- Method: Debugger class>>maximumOpenDebuggers: (in category 'preferences') -----
+ maximumOpenDebuggers: anInteger
+ 	self assert: anInteger >= 1 description: 'value must be 1 or higher'.
+ 	MaximumOpenDebuggers := anInteger!

Item was changed:
  ----- Method: Debugger class>>openOn:context:label:contents:fullView: (in category 'opening') -----
  openOn: process context: context label: titleOrNil contents: contentsStringOrNil fullView: bool
  	"Kind of private. Open a notifier or a full debugger in response to an error, halt, or notify. Opens a project-specific debugger. Decorates that invocation with (1) recursive-error detection and (2) error logging, which are both independent from the active GUI framework, that is, MVC or Morphic.
  	Note that clients should debug processes through Process >> #debug instead of calling this method directly."
  	| ap title |
  	title := titleOrNil ifNil: ['Debugger' translated].
  	ap := Processor activeProcess.
+ 	self checkDebuggerFlood.
  	"If the active process re-enters this method again, something went wrong with invoking the debugger."
  	ap hasRecursiveError ifTrue: [
  		ap clearErrorRecursionFlag.
  		^ ToolSet handleRecursiveError: title].
  	"Explicitely handle logging exceptions. No need to bother the recursion mechanism here."
  	[Preferences logDebuggerStackToFile
  		ifTrue: [Smalltalk logSqueakError: title inContext: context]
  	] on: Error do: [:ex |
  		Preferences disable: #logDebuggerStackToFile.
  		ToolSet debugException: ex].
  	"If project-specific debuggers mess up, we have to flag that recursion here. Se above."
  	[ap setErrorRecursionFlag.
  		self informExistingDebugger: context label: title.
  		^ Project current debuggerClass
  			openOn: process context: context label: title contents: contentsStringOrNil fullView: bool
  	] ensure: [ap clearErrorRecursionFlag].!

More information about the Squeak-dev mailing list