<div dir="ltr">Hi Ben,<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 24, 2016 at 10:44 PM, Ben Coman <span dir="ltr">&lt;<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">On Thu, Feb 25, 2016 at 3:06 AM, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt; On Wed, Feb 24, 2016 at 7:23 AM, Ben Coman &lt;<a href="mailto:btc@openinworld.com">btc@openinworld.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Just sharing a passing thought so I don&#39;t forget it before I have time<br>
&gt;&gt; to think more deeply on it.<br>
&gt;&gt;<br>
&gt;&gt; Several parts of Pharo (like SHTextStyler) are designed to have a<br>
&gt;&gt; background process running, and when new input arrives that process is<br>
&gt;&gt; killed so another can be immediately started - and sometimes we seem<br>
&gt;&gt; to end up with large amounts of zombie processes.<br>
&gt;&gt;<br>
&gt;&gt; As I poke around Process&gt;&gt;terminate, I wonder if a different approach<br>
&gt;&gt; would be to have a Process&gt;&gt;restart.  I see there is Context&gt;&gt;restart.<br>
&gt;&gt;<br>
&gt;&gt; The starting the background process might look like...<br>
&gt;&gt;<br>
&gt;&gt;     stylingProcess := [ [ &quot;do stuff with nextData&quot;. self suspend ]<br>
&gt;&gt; repeat ] forkAt: 30.<br>
&gt;&gt;<br>
&gt;&gt; and the code in the main morphic priority 40 thread might look like...<br>
&gt;&gt;<br>
&gt;&gt;    sylingProcess suspend.<br>
&gt;&gt;    nextData := &#39;blah&#39;.<br>
&gt;&gt;    sylingProcess restart.<br>
&gt;<br>
&gt;<br>
&gt; Hi Ben, so I&#39;m assuming restart differs from resume.  Am I right in thinking<br>
&gt; it cuts back the process to the &quot;start&quot;?  Is the start the block from which<br>
&gt; the process was spawned, the argument to fork or forkAt:?<br>
<br>
</span>Thats right.  Essentially like Exception&gt;&gt;retry, to do something like this...<br>
<br>
    restart := false.<br>
    workAvailable := Semaphore new.<br>
    process :=<br>
    [   [  Transcript crShow: &#39;At the start&#39;.<br>
            work := 0.<br>
            [   work := work + 1.<br>
                Transcript crShow: &#39;working on &#39; , work printString.<br>
                1 second wait.<br>
                work&gt;8 ifTrue:<br>
                [   [Transcript crShow: &#39;Work complete.&#39;] fork.<br>
                    workAvailable wait.<br>
                    restart := true.<br>
                ].<br>
                restart ifTrue: [self error].<br>
                work<br>
            ] repeat.<br>
        ] on: Error do: [:err| restart := false. err retry].<br>
    ] newProcess name:&#39;My Restartable Worker&#39;.<br>
    process resume.<br>
<br>
    &quot;later do...&quot;<br>
    restart := true.<br>
    &quot;or after work complete...&quot;<br>
    workAvailable signal.<br>
<br>
    &quot;later still do...&quot;<br>
    process terminate<br>
<br>
...except being able to interrupt the process anytime,<br>
i.e. not needing to wait to get to &quot;restart ifTrue: [self error].&quot;<br></blockquote><div><br></div><div>It can be built simply above signalException:.  So...</div><div><br></div><div>Process class methods for instance creation</div><div>forBlock: aBlockClosure priority: anInteger </div><div><span class="" style="white-space:pre">        </span>&quot;Answer an instance of me that has suspended aContext at priority anInteger.&quot;</div><div><br></div><div><span class="" style="white-space:pre">        </span>&lt;primitive: 19&gt; &quot;Simulation guard&quot;</div><div><span class="" style="white-space:pre">        </span>| newProcess |</div><div><span class="" style="white-space:pre">        </span>(newProcess := self new)</div><div><span class="" style="white-space:pre">                </span>suspendedContext:</div><div><span class="" style="white-space:pre">                        </span>[[[newProcess result: aBlockClosure value.</div><div><span class="" style="white-space:pre">                        </span>   false]</div><div><span class="" style="white-space:pre">                        </span><span style="white-space:pre">        </span><span class="" style="white-space:pre">        </span>on: ProcessRestart</div><div><span class="" style="white-space:pre">                        </span><span style="white-space:pre">        </span><span class="" style="white-space:pre">        </span>do: [:ex| true]]</div><div><span class="" style="white-space:pre">                                </span>whileTrue.</div><div><span class="" style="white-space:pre">                        </span>&quot;Since control is now at the bottom there is no need to terminate (which</div><div><span class="" style="white-space:pre">                        </span> runs unwinds) since all unwinds have been run.  Simply suspend.</div><div><span class="" style="white-space:pre">                        </span> Note that we must use this form rather than e.g. Processor suspendActive</div><div><span class="" style="white-space:pre">                        </span> so that isTerminated answers true.  isTerminated requires that if there is a</div><div><span class="" style="white-space:pre">                        </span> suspended context it is the bottom-most, but using a send would result in</div><div><span class="" style="white-space:pre">                        </span> the process&#39;s suspendedContext /not/ being the bottom-most.&quot;</div><div><span class="" style="white-space:pre">                        </span> newProcess suspend] asContext;</div><div><span class="" style="white-space:pre">                </span>priority: anInteger.</div><div><span class="" style="white-space:pre">        </span>^newProcess</div><div> </div><div>Process methods for process state change</div><div>restart</div><div><span style="white-space:pre">        self signalException: </span>ProcessRestart<br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">btw, The requirement for the fork in &quot;[Transcript crShow: &#39;Work<br>
complete.&#39;] fork&quot;<br>
is strange. Without it the semaphore does not wait, which seems a bug.<br></blockquote><div><br></div><div>Is there a missing yield somewhere?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
btw2, I needed to hack OCUndeclaredVariableWarning&gt;&gt;defaultAction to<br>
stop the transcript being polluted by unknown playground variables. No<br>
warranty on whether this is suitable to be permanent...<br>
    className = &#39;UndefinedObject&#39; ifFalse: [<br>
         self methodNode selector ifNotNil: [self crTrace: className,<br>
&#39;&gt;&gt;&#39;, selector, &#39; &#39;]<br>
         ifNil: [self traceCr:&#39;&#39;].<br>
         self traceCr: &#39;(&#39; , varName , &#39; is Undeclared1) &#39;.<br>
     ].<br>
<span class=""><br>
<br>
<br>
<br>
On Thu, Feb 25, 2016 at 2:56 AM, Max Leske &lt;<a href="mailto:maxleske@gmail.com">maxleske@gmail.com</a>&gt; wrote:<br>
&gt; Fast spawning processes are very hard to debug (e.g. in the process browser).<br>
<br>
</span>This is exactly the use case I was thinking of.  Often they&#39;ve been<br>
and gone before you even know they are there.  Having a permanent<br>
process aids discoverability of system background functionality.<br>
<br>
cheers -ben<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>