Hi Andreas,<br><br><div class="gmail_quote">On Thu, Dec 15, 2011 at 11:00 PM, Andreas Raab <span dir="ltr">&lt;<a href="mailto:andreas.raab@gmx.de">andreas.raab@gmx.de</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On 12/16/2011 3:33, Levente Uzonyi wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Thu, 15 Dec 2011, Christopher Oliver wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Thu, 15 Dec 2011 11:35:55 +0100<br>
I added a tty output debug to<br>
MorphicProject&gt;&gt;interruptName:<u></u>preemptedProcess:, and I found<br>
that Processor&gt;&gt;preemptedProcess occasionally answers the system weak<br>
array finalization process. Yikes! This isn&#39;t what we want to debug at<br>
all. Are we being adequately clever<br>
in determining which process to debug?<br>
</blockquote>
<br>
I&#39;m pretty sure that the currently running process is interrupted. After<br>
GC (which happens often during calculations with LargeIntegers) this is<br>
likely to be the finalization process.<br>
</blockquote>
<br></div>
Correct. To make matters worse, when an interrupt is signaled in the midst of GC, the signal will be delivered after the GC cycle completes, therefore almost guaranteeing that the interrupted process will be the finalization process.<br>

<br>
And so the determination of the process to be interrupted is moderately stupid. What we&#39;d really need to do is to start a slightly leaner version of CPUWatcher, i.e., instead of blindly interrupting whatever process is active, start sampling the running processes and after a short while (100-500 ms) decide which process to kick[*]. Plus, after that ensure that the UI is actually responsive so that the user can interact with the system and if not, keep kicking processes unless the system becomes interactive again. Alas, not a trivial task to be solved.<br>

<br>
[*] A more radical version would suspend *all* user processes and let the user decide which of the suspended processes to inspect. This might have some interesting side effects though...<br></blockquote><div><br></div><div>
it&#39;s smetimes helpful to look at other systems&#39; approaches.  In VisualWorks there is no special interrupt handling in the VM; the keyboard event comes in like any other:</div><div><br></div><div>keyAt: keyNumber character: aCharacter alternative: alternativeCharacter down: isDownTransition</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>&quot;A keyboard key has been pressed or released; take appropriate action&quot;</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| keyboardEvent |</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>(self state isModifierKey: aCharacter) ifTrue: [^self].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(self <b>allProcessInterruptMatchesCharacter</b>: aCharacter</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>inTransition: isDownTransition)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifTrue: </div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^(#{CraftedSmalltalk.DebuggerService} valueOrDo: [Processor])</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span><b>interruptAllUserProcesses</b>].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(self warpToLauncherMatchesCharacter: aCharacter</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>inTransition: isDownTransition)</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifTrue: </div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>[^#{VisualLauncher} ifDefinedDo: [:launcherClass | launcherClass raiseOrOpen]].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>(aCharacter = self state class <b>interruptKeyValue</b> and: [isDownTransition])</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: </div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>[(self state <b>shiftDown</b> or: [(keyNumber bitAnd: 256) ~= 0])</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [[<b>EmergencyWindow open</b>] fork]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifFalse: </div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span>[(#{CraftedSmalltalk.DebuggerService} valueOrDo: [Processor])</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                </span><b>interruptActiveUserProcess</b>]]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: </div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[isDownTransition</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifTrue: [keyboardEvent := KeyPressedEvent new]</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>ifFalse: [keyboardEvent := KeyReleasedEvent new].</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>keyboardEvent := keyboardEvent</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>code: aCharacter</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>meta: (self state metaState bitOr: (keyNumber bitShift: -8))</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                                </span>alternative: alternativeCharacter.</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>self addMetaInput: (keyboardEvent window: window)] </div>
<div><br></div><div>further, UserInterrupt is a signal that can be handled, and there is some special interpretation applied before raising that signal:</div><div><br></div><div>ProcessorScheduler&gt;&gt;interruptActiveUserProcess</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| proc deb |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>proc := self runableProcesses</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>detect: [:p | p isSystemProcess not]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifNone: [nil].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(proc isNil and: [Window currentWindow notNil])</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [proc := Window currentWindow windowProcess].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>proc isNil</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [^self interruptAllUserProcesses].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(deb := proc environmentAt: #debugger) notNil</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [^deb abortDebugOperationInProcess: proc].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>proc isUnderDebug</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [^DebuggerService abortDebuggingFor: proc].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>proc interruptWith: </div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[Object userInterruptSignal </div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>interruptWith: thisContext sender sender</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span>errorString: (#exceptUserInterrupt &lt;&lt; #dialogs &gt;&gt; &#39;User Interrupt&#39;)]</div><div><br></div><div>DebuggerService class&gt;&gt;interruptActiveUserProcess</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>| proc |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>proc := self getActiveUserProcess.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>proc isNil</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [proc := self getCurrentWindowProcess].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>proc isNil</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [^self interruptAllUserProcesses].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>proc isUnderDebug</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [^proc debugger abortDebugOperationInProcess: proc].</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>proc interruptWith:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[Object userInterruptSignal</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>interruptWith: thisContext sender sender</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>errorString: (#UserInterrupt &lt;&lt; #pdp &gt;&gt; &#39;User Interrupt&#39;)]</div><div><br></div><div>This is a variation on having a smarter <span class="Apple-style-span" style="border-collapse:collapse;font-family:arial,sans-serif;font-size:13px">Processor&gt;&gt;preemptedProcess.  It seems to me that using the GUI to select the active process makes sense, that when using the debugger, interrupting simulation makes sense, and that making UserInterrupt a signal is a really, really good thing, especially for deploying applications.</span></div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Cheers,<br><font color="#888888">
  - Andreas</font></blockquote></div>-- <br>best,<div>Eliot</div><br>