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