Hi all,
I have made the following observation and wonder if this is a bug or such. $ a := [[(Delay forSeconds: 300) wait] ensure: ['Terminated' printNl]] fork. $ a terminate Process(nil at userSchedulingPriority, ready to run) $ a terminate 'Terminated' Process(nil at userSchedulingPriority, terminated) To work around such sticky processes I have decided to use a [proc isTerminated] whileFalse: [proc terminate] construct. regards holger _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On 12/18/2010 11:38 AM, Holger Hans Peter Freyther wrote:
> Hi all, > > To work around such sticky processes I have decided to use a [proc > isTerminated] whileFalse: [proc terminate] construct. > Sometimes I am also ending up with this backtrace. Object: nil error: did not understand #goodness: MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254) UndefinedObject(Object)>>doesNotUnderstand: #goodness: (SysExcept.st:1407) optimized [] in BlockClosure class>>exceptionHandlerSearchBlock (BlkClosure.st:16) [] in MessageNotUnderstood(Exception)>>instantiateNextHandlerFrom: (ExcHandling.st:340) MethodContext(ContextPart)>>scanBacktraceForAttribute:do: (ContextPart.st:449) MessageNotUnderstood(Exception)>>instantiateNextHandlerFrom: (ExcHandling.st:342) MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254) UndefinedObject(Object)>>doesNotUnderstand: #>= (SysExcept.st:1407) optimized [] in Delay class>>startDelayLoop (Delay.st:166) SortedCollection>>insertionIndexFor:upTo: (SortCollect.st:728) [] in SortedCollection>>merge (SortCollect.st:531) SortedCollection(SequenceableCollection)>>reverseDo: (SeqCollect.st:958) SortedCollection>>merge (SortCollect.st:537) SortedCollection>>last (SortCollect.st:121) Delay class>>activeDelay (Delay.st:78) Delay class>>handleDelayRequestor (Delay.st:104) optimized [] in Delay class>>runDelayProcess (Delay.st:124) [] in BlockClosure>>ifCurtailed: (BlkClosure.st:287) BlockClosure>>ensure: (BlkClosure.st:269) BlockClosure>>ifCurtailed: (BlkClosure.st:273) Delay class>>runDelayProcess (Delay.st:120) optimized [] in Delay class>>startDelayLoop (Delay.st:168) [] in Process>>onBlock:at:suspend: (Process.st:392) BlockClosure>>on:do: (BlkClosure.st:193) [] in Process>>onBlock:at:suspend: (Process.st:393) BlockClosure>>ensure: (BlkClosure.st:269) [] in Process>>onBlock:at:suspend: (Process.st:370) [] in BlockClosure>>asContext: (BlkClosure.st:179) BlockContext class>>fromClosure:parent: (BlkContext.st:68) _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
On 12/18/2010 11:59 AM, Holger Hans Peter Freyther wrote:
> On 12/18/2010 11:38 AM, Holger Hans Peter Freyther wrote: >> Hi all, > >> >> To work around such sticky processes I have decided to use a [proc >> isTerminated] whileFalse: [proc terminate] construct. >> and one more related question. Is there something about Semaphores and terminated processes? I have no good test case yet but I think. A: [ [ ] ensure: [ mutex critical: ['Sometimes never entered' printNl. allProcesses remove: Processor activeProcess]. ] ] fork B: mutex criticial: [allProcesses do: [:each | each terminate ]]. I think sometimes this statement will not executed when the process is being terminated. What I am trying to do is to have a cleanup handler for processes. E.g. to make a process remove itself from a list of processes. Is there a better way to achieve this goal? _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Holger Freyther
On 12/18/2010 11:38 AM, Holger Hans Peter Freyther wrote:
> $ a := [[(Delay forSeconds: 300) wait] ensure: ['Terminated' printNl]] fork. > $ a terminate > Process(nil at userSchedulingPriority, ready to run) > $ a terminate > 'Terminated' > Process(nil at userSchedulingPriority, terminated) Not a bug, it won't happen when you run the program outside the REPL (or if the REPL let processes run in the background. > To work around such sticky processes I have decided to use a [proc > isTerminated] whileFalse: [proc terminate] construct. It's enough to do proc terminate. [proc isTerminated] whileFalse: [Processor yield] For example: st> Eval [ proc := [[(Delay forSeconds: 300) wait] ensure: ['Terminated' printNl]] fork. proc terminate. [proc isTerminated] whileFalse: [Processor yield]. proc ] 'Terminated' Process(nil at userSchedulingPriority, terminated) The reason is that termination is a non-trivial operation which involves sending the ProcessBeingTerminated exception. It also may cause a context switch. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Holger Freyther
On 12/18/2010 12:31 PM, Holger Hans Peter Freyther wrote:
> A: > [ > [ ] ensure: [ > mutex critical: ['Sometimes never entered' printNl. allProcesses remove: > Processor activeProcess]. > ] > ] fork > > B: > mutex criticial: [allProcesses do: [:each | each terminate ]]. > > I think sometimes this statement will not executed when the process is being > terminated. What I am trying to do is to have a cleanup handler for processes. > E.g. to make a process remove itself from a list of processes. This should work. It may be that you're not waiting long enough. mutex := Semaphore forMutualExclusion. allProcesses := IdentitySet new. i := 0. p := [ :x | [ (Delay forMilliseconds: x) wait ] ensure: [ mutex critical: [i := i + 1. allProcesses remove: Processor activeProcess]. ] ]. 1000 timesRepeat: [ (allProcesses add: (p newProcessWith: {Random between: 300 and: 1000})) resume ]. (Delay forMilliseconds: 450) wait. mutex critical: [allProcesses do: [:each | each terminate ]]. (Delay forMilliseconds: 2000) wait. i printNl. If you change the final "2000" you indeed get an output that is less than 1000. That said, this reproduces the other bug in Delay, so thanks. :) Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
In reply to this post by Holger Freyther
On 12/20/2010 11:06 AM, Holger Hans Peter Freyther wrote:
> On 12/18/2010 08:00 PM, Paolo Bonzini wrote: > >> >> Aha, I could now reproduce what you meant, but it's not a bug. The problem is >> that if you're already in the #ensure: block, or in the #critical: block, >> #terminate will be able to unwind it. So, #ensure: is fundamentally >> incompatible with #terminate (at least as it is implemented now). I have to >> think more about it. > > I assume it is the same for sending any message? I have moved from terminate > to send a simple Notification/Exception. But as it is mostly implemented the > same way, I face the same issue? I think ProcessBeingTerminated is different, but it has the problem that it is more akin to #ifCurtailed: than to #ensure:. It would be interesting to see what other dialects do. But it is better to think of #terminate as a very bad idea in general :) and rethink processes to implement *interruption* rather than termination. Another possibility in your case is to implement the processes collection using a wrapper, so that iteration will filter out processes that have terminated. I'm also thinking of moving #queueInterrupt: to a primitive or something like that so that it's not preemptable/interruptible. This means that instead of removing itself from the collection, a terminating process could *atomically* ask another process to do the removal. Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |