On 08 Jan 2016, at 3:07 , Denis Kudriashov <dionisiydk@gmail.com> wrote:
Yes. When process suspend called during termination process has no more semaphore as suspendingList
Which is why in terminate I do myList := self suspend. So the semaphore *should* still be the suspendingList, just without the process actually on the list... Seems to me something strange happens between setting activeProcess using execute:onBehalfOf: and when it reaches the ifCurtailed block, at that point the terminating thread is no longer the "active" process. Cheers, Henry
2016-01-08 14:56 GMT+01:00 Henrik Johansen <henrik.s.johansen@veloxit.no <mailto:henrik.s.johansen@veloxit.no>>: Ugh, there's a bug with the Processor activeProcess suspendingList, I only checked in the case where it *should* signal. Take it as an inspiration :)
Cheers, Henry
On 08 Jan 2016, at 2:40 , Henrik Johansen <henrik.s.johansen@veloxit.no <mailto:henrik.s.johansen@veloxit.no>> wrote:
Here's an alternative implementation, which, instead of checking for the new method name, hooks into the existing unwind machinery to execute the waitIfCurtailed: argument. Which removes the special case from Process >> #terminate, but at the added cost that in-progress unwinds are executed as if the (suspended) terminating thread they started executing on, is still the active process. (Which, arguably, should be done anyways)
Cheers, Henry
<SignalUsingUnwindMachinery.cs>
"This runs on UI thread, pri 40" waiter := Semaphore new. waiter2 := Semaphore new. lock := Semaphore forMutualExclusion.
proc := [lock critical2: [ Transcript crShow: '1 start'. waiter wait. Transcript crShow: '1 done'.]] newProcess. proc priority: 70. proc resume.
proc2 := [lock critical2: [ Transcript crShow: '2 start'. waiter2 wait. Transcript crShow: '2 done'. ]] newProcess. proc2 priority: 15. proc2 resume.
"Yield for proc2 so it gets to waiting on lock" 1 second wait. "Signal waiter and yield, causing proc1 to run, and release the lock. lock will then remove proc2 from waiting list" waiter signal. Processor yield. "We have a higher pri than proc2, and will resume execution here before proc2 has chance to run" proc2 terminate. "proc2 has been curtailed before running, thus ifCurtailed: guard is still on stack and will be run as part of termination." (lock instVarNamed: 'excessSignals') 1
On 07 Jan 2016, at 11:09 , Denis Kudriashov <dionisiydk@gmail.com <mailto:dionisiydk@gmail.com>> wrote:
Ok. slice 17340 <https://pharo.fogbugz.com/f/cases/17340/Semaphore-critical-should-handle-int...> in inbox. It is only touches current #critical: implementation. It is not about deprecation wrong semaphore usage
2016-01-07 9:55 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com <mailto:dionisiydk@gmail.com>>:
2016-01-07 0:15 GMT+01:00 Ben Coman <btc@openinworld.com <mailto:btc@openinworld.com>>:
I'm not qualified to judge, but is sounds okay. I have an alternative proposal to consider that hopefully might remove Semaphore handling completely from Process>>terminate.
What if we have a wait primitive that instead of returning itself (i.e. a Semaphore), it always returns true. Then if the process is terminated while the primitive is waiting, before it consumes a signal, the assignment to signalConsumed never occurs. Then we have...
critical: mutuallyExcludedBlock signalConsumed := false. [ signalConsumed := self primWaitSucceeded. blockValue := mutuallyExcludedBlock value ] ensure: [ signalConsumed ifTrue: [self signal] ]. ^blockValue
It *feels* more atomic. Someone knowledgeable with the vm would need to advise whether after the primitive wakes up and consumes a signal, the assignment into signalConsumed can be guaranteed to occur before the process gets a chance to terminate, even if the primitive needs to directly poke the value into signalConsumed.
To me it is better too. But it requires changes in VM primitive which I'm can't provide. So I will implement my idea. Do you ok with the name #waitIfInterrupted?