Hi Ben,
On Wed, Feb 24, 2016 at 10:44 PM, Ben Coman btc@openinworld.com wrote:
On Thu, Feb 25, 2016 at 3:06 AM, Eliot Miranda eliot.miranda@gmail.com wrote:
On Wed, Feb 24, 2016 at 7:23 AM, Ben Coman btc@openinworld.com 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]."
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
complete.'] fork" is strange. Without it the semaphore does not wait, which seems a bug.
Is there a missing yield somewhere?
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 maxleske@gmail.com 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
squeak-dev@lists.squeakfoundation.org