There are a potential of having incorrect behavior , when terminating
a preempted or waiting process: with introduction of ProcessLocalVariable, it is essential that context unwinding procedure should be performed only for currently active process. Here the proposal how to ensure this: if terminating process is not active process we should do the following: suspendedContext := proc suspendedContext. currentProces := Processor activeProcess. proc suspendedContext: [ Processor activeProcess terminateFromContext: suspendedContext. Processor switchToProcess: currentProcess ] asContext. Processor switchToProcess: proc. here #switchToProcess: is explicit switch (bypassing scheduling logic). If we don't care about immediate termination of process and getting back to process who initiated termination as soon as possible, then simply do: process terminateSoon. which can be implemented as: Process>>terminateSoon | termContext | termContext := suspendedContext. suspendedContext := [ self terminateFromContext: termContext. self suspend ] asContext. Processor yield. -- Best regards, Igor Stasenko AKA sig. |
Another improvement would be to marry the process termination with
exception handling, and nicely signal ProcessTerminatedException. This offers many practical benefits, since then we could write: [ ... ] on: ProcessTerminatedException do: [:ex | "oh man we're been terminated" ]. But i'm not expert in exception handling. Can someone give me a sample, how to signal such exception in potential #terminateFromContext: method? 2009/5/1 Igor Stasenko <[hidden email]>: > There are a potential of having incorrect behavior , when terminating > a preempted or waiting process: > > with introduction of ProcessLocalVariable, it is essential that > context unwinding procedure should be performed only > for currently active process. > > Here the proposal how to ensure this: > > if terminating process is not active process we should do the following: > > suspendedContext := proc suspendedContext. > currentProces := Processor activeProcess. > proc suspendedContext: [ Processor activeProcess > terminateFromContext: suspendedContext. Processor switchToProcess: > currentProcess ] asContext. > Processor switchToProcess: proc. > > here #switchToProcess: is explicit switch (bypassing scheduling logic). > > If we don't care about immediate termination of process and getting > back to process who initiated termination as soon as possible, then > simply do: > process terminateSoon. > > which can be implemented as: > > Process>>terminateSoon > | termContext | > termContext := suspendedContext. > suspendedContext := [ self terminateFromContext: termContext. self > suspend ] asContext. > Processor yield. > > > > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
On Fri, May 1, 2009 at 3:11 AM, Igor Stasenko <[hidden email]> wrote:
> Another improvement would be to marry the process termination with > exception handling, > and nicely signal ProcessTerminatedException. Which is pretty much what VW does, I think. > This offers many practical benefits, since then we could write: > > [ ... ] on: ProcessTerminatedException do: [:ex | > "oh man we're been terminated" > ]. > > But i'm not expert in exception handling. > Can someone give me a sample, how to signal such exception in potential > #terminateFromContext: method? Seems like you would just do "ProcessTerminatedException signal" as long as the receiver was the active process. If not the active process, you would have to replace the suspended context with a new context that will signal the exception as soon as the process is next run. The strange thing about this implementation is that you can write code that actually prevents your process from being terminated. I'm not saying that's a bad thing (maybe it's even a good thing for certain pieces of code) but it certainly changes the semantics of #terminate a little. :) And that being the case, the name ProcessTerminatedException is a bit misleading because it implies that the process already *has* been terminated. TerminateProcessException, TerminateProcessRequest, or just TerminateProcess would be more accurate. Julian |
2009/5/1 Julian Fitzell <[hidden email]>:
> On Fri, May 1, 2009 at 3:11 AM, Igor Stasenko <[hidden email]> wrote: >> Another improvement would be to marry the process termination with >> exception handling, >> and nicely signal ProcessTerminatedException. > > Which is pretty much what VW does, I think. > >> This offers many practical benefits, since then we could write: >> >> [ ... ] on: ProcessTerminatedException do: [:ex | >> "oh man we're been terminated" >> ]. >> >> But i'm not expert in exception handling. >> Can someone give me a sample, how to signal such exception in potential >> #terminateFromContext: method? > > Seems like you would just do "ProcessTerminatedException signal" as > long as the receiver was the active process. If not the active > process, you would have to replace the suspended context with a new > context that will signal the exception as soon as the process is next > run. > > The strange thing about this implementation is that you can write code > that actually prevents your process from being terminated. I'm not > saying that's a bad thing (maybe it's even a good thing for certain > pieces of code) but it certainly changes the semantics of #terminate a > little. :) I'm now almost done implementing it. Its behavior will be different than regular exception handling. What it will do is: 1. find handler context, if any 2. rewind the stack up to handler context 3. evaluate the handler block (note, that any flow control methods like "pass, return .. will be simply ignored") 4. repeat from (1) until there are no contexts on stack so, this all is to ensure, that a) stack is rewounded b) all [... ] on: TerminateProcess do: [ .. ] during rewinding is handled > And that being the case, the name > ProcessTerminatedException is a bit misleading because it implies that > the process already *has* been terminated. TerminateProcessException, > TerminateProcessRequest, or just TerminateProcess would be more > accurate. > Thanks for a better name. I will rename it to 'TerminateProcess'. > Julian > > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Igor Stasenko
Igor Stasenko wrote:
> Another improvement would be to marry the process termination with > exception handling, > and nicely signal ProcessTerminatedException. > This offers many practical benefits, since then we could write: > > [ ... ] on: ProcessTerminatedException do: [:ex | > "oh man we're been terminated" > ]. A simpler and more robust alternative that I talked to Eliot about yesterday is to simply have another indirection for activeProcess, i.e., ProcessorScheduler>>activeProcess "Answers the currently active process" ^activeProcess currentProcess Process>>currentProcess "If I am pretending to be another process, answer it. Otherwise answer self" currentProcess ifNil:[^self]. "Pass the request on since we could be debugging unwind issues" ^currentProcess currentProcess Why is this advantageous? Several reasons: a) It is not only useful for termination, but also for debugging. The debugger can provide the currently suspended process and simulated code will pick up the "right" identity (as the above illustrates this way you would be able to debug unwind blocks and have the code pick up the bindings from the process being terminated in the debugger :) b) There is no question about either priority, what the terminated process status is when exiting #terminate etc. as it is within the calling process execution context (otherwise the terminating process might never complete if it has a low priority). c) It rules out a whole class of errors that can happen if you rely on exception handling being implemented "correctly" in the users code. For example, there are several places that handle Exception instead of Error, Halt (or whatever they really should handle). Handling ProcessTermination "accidentally" is obviously error prone and I don't think user code should have a choice of handling it (there are perfectly good ways to implement such a feature yourself if you really need it and there is no good reason for user code by default to deny termination; not even accidentally). d) Error handling occurs in the calling process. That's important because often termination is something done as a last resort and it is not unusal to have different error handlers when you terminate a process compared to the error handlers that you need when you run it normally. Cheers, - Andreas |
2009/5/2 Andreas Raab <[hidden email]>:
> Igor Stasenko wrote: >> >> Another improvement would be to marry the process termination with >> exception handling, >> and nicely signal ProcessTerminatedException. >> This offers many practical benefits, since then we could write: >> >> [ ... ] on: ProcessTerminatedException do: [:ex | >> "oh man we're been terminated" >> ]. > > A simpler and more robust alternative that I talked to Eliot about yesterday > is to simply have another indirection for activeProcess, i.e., > > ProcessorScheduler>>activeProcess > "Answers the currently active process" > ^activeProcess currentProcess > > Process>>currentProcess > "If I am pretending to be another process, answer it. > Otherwise answer self" > currentProcess ifNil:[^self]. > "Pass the request on since we could be debugging unwind issues" > ^currentProcess currentProcess > > Why is this advantageous? Several reasons: > > a) It is not only useful for termination, but also for debugging. The > debugger can provide the currently suspended process and simulated code will > pick up the "right" identity (as the above illustrates this way you would be > able to debug unwind blocks and have the code pick up the bindings from the > process being terminated in the debugger :) > > b) There is no question about either priority, what the terminated process > status is when exiting #terminate etc. as it is within the calling process > execution context (otherwise the terminating process might never complete if > it has a low priority). > terminated asap. For old one, i boosting its priority to maximum. Speaking about priority, i would care just about a single solid rule: - ensure that a process/context which is sends #terminate (to other process or to itself) , doesn't having a chance to regain control before terminate request is fully complete. But also there could be the case, that sender don't really cares, when required process should terminate - its just want it to be terminated eventually. For this i propose adding a #terminateSoon message to Process protocol. > c) It rules out a whole class of errors that can happen if you rely on > exception handling being implemented "correctly" in the users code. For > example, there are several places that handle Exception instead of Error, > Halt (or whatever they really should handle). Handling ProcessTermination > "accidentally" is obviously error prone and I don't think user code should > have a choice of handling it (there are perfectly good ways to implement > such a feature yourself if you really need it and there is no good reason > for user code by default to deny termination; not even accidentally). > Right. But its more a social problem. Nothing stops your from putting a rewind block which taking thisContext and flying away to a high sky. We providing an implementation which works unless its abused (as everything else in smalltalk). > d) Error handling occurs in the calling process. That's important because > often termination is something done as a last resort and it is not unusal to > have different error handlers when you terminate a process compared to the > error handlers that you need when you run it normally. > Andreas, i thought about it just today morning (what a coincidense? :). Really, its not a problem to create a proxy object which pretends to be a Process. What i like in smalltalk , is breaking the dogmas which often seem scary & dangerous , but in reality just a taints from a C world. After all - everything is objects, right? :) But its hard to measure the cost of adding such pretender and possible side effects. There are multiple problematic places which treating Processes mostly as a dummy state holder (suspendedContext/list) both in VM and image side. Of course, i can wipe/remix everything in Process and still make it able to run with new scheduler. But this having a cost of losing backward compatibility. Or... write a code which migrating instances NewProcess <--> OldProcess, so then i could switch between them easily (but still this is a pain in the ass ;) ). This is what i planning to do for Delays, since i made AdvancedDelay to be a subclass of Object , because its having 1 less ivar: delayDuration resumptionTime waitingProcess. I almost done writing new delays.. - it don't needs to have own high-priority process, mainly because of cooperation with new scheduler (its reusing interruptProcess to do all atomic stuff). - new Delays no longer needs a semaphore, because it can control resume/suspend by itself, as well as can be passed to primitive which signals it - because primitive which fetching even signals from VM is simply fills an array with integers. Scheduler free to interpret them as it likes to (as an index in special/external objects array or somewhere else). With this new primitive i really consider about unification and - remove ExternalSemaphoreTable, and keep this array as an ivar in Processor - in VM, unify all places as well, by removing all references to 'semaphore' and replacing them with more abstract thing - signals. VM simply doesn't needs to know, what signal means and who is behind it - for VM its just an integer value, nothing more. It simply fills an array with these integers and let Processor handle them. This, of course related to a well-known objects from special objects table, which is 'known to be a semaphore'. They could be just a normally 1-based indexed, and scheduler will reserve these slots for appropriate objects i.e.: TheLowSpaceSemaphore := 1. ProcessSignalingLowSpace := 2. etc.. and add a convenienve methods, like: Processor>>registerLowSpaceHandler: anObject signalHandlers at: TheLowSpaceSemaphore put: anObject P.S a bit long post... > Cheers, > - Andreas > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |