Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 1 participants
- 144619 messages
[pharo-project/pharo-core]
by GitHub
Branch: refs/tags/30857
Home: https://github.com/pharo-project/pharo-core
Sept. 18, 2014
Re: [Pharo-dev] I'm confused about Process>>isTerminated
by Max Leske
Hi Eliot,
On 18.09.2014, at 01:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
> Hi Max,
>
> On Wed, Sep 17, 2014 at 1:59 PM, Max Leske <maxleske(a)gmail.com> wrote:
> Hi Eliot
>
>
> On 16.09.2014, at 20:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
>
>> Hi Max,
>>
>> On Tue, Sep 16, 2014 at 11:05 AM, Max Leske <maxleske(a)gmail.com> wrote:
>> Hi
>>
>> As always when I want to check if a process has died I get very confused by #isTerminated and Iâm wondering if I just donât get how itâs supposed to work or if there are others that share my confusion.
>>
>> Old implementation:
>>
>> isTerminated
>>
>> self isActiveProcess ifTrue: [^ false].
>> ^suspendedContext isNil
>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>> from value and there is nothing more to do."
>> suspendedContext isBottomContext
>> and: [ suspendedContext pc > suspendedContext startpc ] ]
>>
>>
>> Pharo 4 implementation:
>>
>> isTerminated
>> self isActiveProcess ifTrue: [^ false].
>> ^suspendedContext isNil
>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>> from value and there is nothing more to do.â
>> suspendedContext isBottomContext
>> and: [ suspendedContext isDead not â<âââââââââââââââââââââââââ new"
>> and: [ suspendedContext pc > suspendedContext startpc ] ] ]
>>
>>
>> The old implementation would break if the suspended context was dead (i.e. the pc was nil) because the send of #> would produce an MNU.
>> The new implementation doesnât fix that, even though it looks like it at first glance: if the pc is nil, the #> send will still happen -> MNU.
>>
>> Off the top of my head it would seem that it should be isDead or: [] not isDead not and:
>>
>> isTerminated
>> self isActiveProcess ifTrue: [^ false].
>> ^suspendedContext isNil
>> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
>> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
>> from value and there is nothing more to do.â
>> suspendedContext isBottomContext
>> and: [ suspendedContext isDead
>> or: [ suspendedContext pc > suspendedContext startpc ] ] ]
>
> Phew. Glad you see that the same way.
>
>> isDead
>> ^ pc isNil
>>
>> and maybe (suspendedContext pc ifNil: [true] ifNotNil: [:pc| pc > suspendedContext startpc]) is more obvious.
>>
>> Anyway, neither implementation will reliably tell me if the process has been terminated:
>> - an inactive process will be suspended when #terminate is sent and report that it has not been terminated (#isSuspended -> true, #isTerminated -> false)
>>
>> except that it *hasn't* been terminated, it is merely in the process of termination. It isn't terminated until all unwind blocks have run, right?
>
> True. Easy to forget when you can just kill -9 on the console⦠:)
>
>>
>> - a properly terminated process will raise an MNU (although apparently not always�)
>>
>> but that's a bug the change I suggested will fix.
>>
>> - all the states in between: no clue
>>
>> I would like to know two things:
>> 1. how can I check if a process has already *received* a #terminate? (I would then assume that the process will die eventually)
>>
>> I don't think you can without putting a critical section around terminate and adding some process-specific variable that is set when you send terminate. termination is not instantaneous (unwind blocks have to be run), so it is potentially interruptible.
>
> Iâve thought about this a bit. I wouldnât really care if I donât get a correct answer about the termination status immediately but I want to have it before the process terminates. In case of something like the following:
>
> ([ 10 seconds asDelay wait ] forkAt: 11) terminate
>
> it can (potentially) take a very long time for the process to terminate. So if I have to poll 3 or 4 times thatâs ok but I donât want to wait for minutes.
> One solution would be to take your idea of the variable, but without the critical block:
>
> terminate
> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>
> | ctxt unwindBlock oldList |
> terminating := true. â<âââââââââââââââââââââââââââââââââââ changed"
> self isActiveProcess
> ifTrue: [
> ctxt := thisContext.
> [ ctxt := ctxt findNextUnwindContextUpTo: nil.
> ctxt isNil ] whileFalse:
> [ (ctxt tempAt: 2) ifNil:
> [ ctxt tempAt: 2 put: nil.
> unwindBlock := ctxt tempAt: 1.
> thisContext terminateTo: ctxt.
> unwindBlock value ]].
> thisContext terminateTo: nil.
> self suspend ]
> ifFalse: [
> "Always suspend the process first so it doesn't accidentally get woken up"
> oldList := self suspend.
> suspendedContext ifNotNil:[
> "Figure out if we are terminating the process while waiting in Semaphore>>critical:
> In this case, pop the suspendedContext so that we leave the ensure: block inside
> Semaphore>>critical: without signaling the semaphore."
> (oldList class == Semaphore and:[
> suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[
> suspendedContext := suspendedContext home.].
>
> "If we are terminating a process halfways through an unwind, try to complete that unwind block first."
> (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [ :outer |
> (suspendedContext findContextSuchThat: [ :c | c closure == (outer tempAt: 1)])
> ifNotNil: [ :inner |
> "This is an unwind block currently under evaluation"
> suspendedContext runUntilErrorOrReturnFrom: inner ]].
> ctxt := self popTo: suspendedContext bottomContext.
> ctxt == suspendedContext bottomContext ifFalse: [
> self debug: ctxt title: 'Unwind error during termination']] ].
>
>
>
> isTerminating
> ^ terminating ifNil: [ ^ false ]
>
>
> With this small modification I can run the example from above and immediately see that it will die eventually.
>
> Iâm aware that one process might not see the change to the variable immediately but as I said, I wouldnât really care.
>
>
> What do you think?
>
> Yes that looks good. But given that branches are atomic (ifTrue: is not a send) why not do
>
> Process>>initialize
> terminating := false.
>
> terminate
> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>
> | ctxt unwindBlock oldList |
> terminating
> ifTrue: [self error: 'Process is already terminated, or being terminated']
> ifFalse: [terminating := true].
> self isActiveProcess
> ifTrue:
> ...
>
> ?
>
> I would suggest a status inst var, as in
>
> Process>>initialize
> status := nil
>
> terminate
> "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
>
> | ctxt unwindBlock oldList |
> status == #terminating
> ifTrue: [self error: 'Process is already terminated, or being terminated']
> ifFalse: [status := terminating].
> self isActiveProcess
> ifTrue:
> ...
>
> but the temptation then is to have lots of different status values and I'm leery of introducing that kind of complication without a strong justification.
Iâve worked a bit on an implementation along your suggestions. I wrote a test which looks like this:
testIsTerminated
| proc |
proc := [ Semaphore new wait ] forkAt: 30.
self deny: proc isSuspended.
self deny: proc isTerminating.
self deny: proc isTerminated.
proc terminate.
self deny: proc isTerminated.
self assert: proc isSuspended.
self assert: proc isTerminating.
[ proc isTerminated ] whileFalse: [ 1 second asDelay wait ]. â<âââââââââââ ???"
self assert: proc isTerminated.
self assert: proc isTerminating
The test works AFAICT (apart from the loopâ¦) but I want to also have a check after the process has terminated. Is there some reliable way to wait for a process to die? I tried something like this for example:
proc run.
self assert: proc isTerminated.
But that locks up the active process (obviously) until I interrupt it manually. If there is such a way, I could also add a method that lets a process x wait for the completion of a process y for example (or not, depending on how difficult it is :) )
Cheers,
Max
>
>
> Cheers,
> Max
>
>>
>> 2. how can I check if a process is *actually* dead? (in case a âhalf deadâ process will still unwind or whatever)
>>
>> see above.
>>
>>
>> What would be necessary to make those tests (or better ones) possible (rewrite the whole process implementation?)?
>>
>>
>> Cheers,
>> Max
>>
>> --
>> best,
>> Eliot
>
>
> --
> best,
> Eliot
Sept. 18, 2014
Re: [Pharo-dev] csv2html the Pharo version
by Serge Stinckwich
Excellent Sven !
Maybe the Douai guys have some really huge cvs that could not be processed
by Pharo.
On Thu, Sep 18, 2014 at 10:28 AM, Sven Van Caekenberghe <sven(a)stfx.eu>
wrote:
> Hi,
>
> Today I came across some bash code on a web page that loves Smalltalk, ah
> the horror ;-)
>
> http://car.mines-douai.fr/2014/09/csv2html/
>
> The goal is to make it easier to look at CSV data, for which a conversion
> to HTML was done. To just look at CSV data in a nice tabular form, we do
> not have to leave Pharo at all.
>
> MultiColumnListModel new
> items: (FileLocator desktop / 'test.csv' readStreamDo: [ :in |
> (NeoCSVReader on: in) emptyFieldValue: ''; upToEnd ]);
> displayBlock: [ :x | x ];
> title: 'CSV Data';
> openWithSpec.
>
> Which results in this nice window:
>
>
> To do a conversion to HTML, debugging the code in Pharo should be
> preferable to doing the same with bash & sed (for most of us anyway).
>
> FileLocator desktop / 'csv.html' writeStreamDo: [ :out | | reader |
> out << '<html><head><title>CSV Data</title></head><body><table
> border=1>'.
> reader := NeoCSVReader on: (FileLocator desktop / 'test.csv') readStream.
> reader emptyFieldValue: ''.
> out << '<tr bgcolor=silver>'.
> reader readHeader do: [ :each | out << '<th>'; << each; << '</th>' ].
> out << '</tr>'.
> reader do: [ :each |
> out << '<tr>'.
> each do: [ :td | out << '<td>'; << td; << '</td>' ].
> out << '</table></body></html>'.
> reader close ].
>
> Which gives the following output:
>
> NeoCSVReader is way more powerful in interpreting CSV files than a simple
> sed one-liner. Doing the same for a collection of files is easy. Maybe a
> little browser could even be written. Who knows, maybe Doru will add
> another tool to GT (TableViewer class>>#openStructuredOn: would do the
> trick I guess) ;-)
>
> Sven
>
> PS: The bash script was actually quite well written, even I could
> read/understand it. Thanks for sharing, it was the inspiration to do this
> little hack.
>
>
--
Serge Stinckwich
UCBN & UMI UMMISCO 209 (IRD/UPMC)
Every DSL ends up being Smalltalk
http://www.doesnotunderstand.org/
Sept. 18, 2014
Re: [Pharo-dev] csv2html the Pharo version
by Luc Fabresse
Hi Sven,
Arg, you got us :-P
Shame on us!
You are completely right that we could have done that in Pharo.
But, Zhi is working since mont on doing realistic robotics simulation on
the cluster of the EMD.
The goal is to use the SAME code both in simulation and in the real robots.
For doing this, he is writing a lot (a LOT) of BASH scripts to
automatically prepare simulations on the cluster nodes.
Since he is not really fluent in Pharo and since it involves so much system
scripting, he is doing it in BASH.
I suspect that he took the least resistant path to code the csv to html ...
Anyway, at some point we will move from this first prototype to another one
so involve Pharo deeper using PhaROS and then we will have more Pharo in
the loop ;-)
Cheers,
#Luc
2014-09-18 10:28 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Hi,
>
> Today I came across some bash code on a web page that loves Smalltalk, ah
> the horror ;-)
>
> http://car.mines-douai.fr/2014/09/csv2html/
>
> The goal is to make it easier to look at CSV data, for which a conversion
> to HTML was done. To just look at CSV data in a nice tabular form, we do
> not have to leave Pharo at all.
>
> MultiColumnListModel new
> items: (FileLocator desktop / 'test.csv' readStreamDo: [ :in |
> (NeoCSVReader on: in) emptyFieldValue: ''; upToEnd ]);
> displayBlock: [ :x | x ];
> title: 'CSV Data';
> openWithSpec.
>
> Which results in this nice window:
>
>
> To do a conversion to HTML, debugging the code in Pharo should be
> preferable to doing the same with bash & sed (for most of us anyway).
>
> FileLocator desktop / 'csv.html' writeStreamDo: [ :out | | reader |
> out << '<html><head><title>CSV Data</title></head><body><table
> border=1>'.
> reader := NeoCSVReader on: (FileLocator desktop / 'test.csv') readStream.
> reader emptyFieldValue: ''.
> out << '<tr bgcolor=silver>'.
> reader readHeader do: [ :each | out << '<th>'; << each; << '</th>' ].
> out << '</tr>'.
> reader do: [ :each |
> out << '<tr>'.
> each do: [ :td | out << '<td>'; << td; << '</td>' ].
> out << '</table></body></html>'.
> reader close ].
>
> Which gives the following output:
>
> NeoCSVReader is way more powerful in interpreting CSV files than a simple
> sed one-liner. Doing the same for a collection of files is easy. Maybe a
> little browser could even be written. Who knows, maybe Doru will add
> another tool to GT (TableViewer class>>#openStructuredOn: would do the
> trick I guess) ;-)
>
> Sven
>
> PS: The bash script was actually quite well written, even I could
> read/understand it. Thanks for sharing, it was the inspiration to do this
> little hack.
>
>
Sept. 18, 2014
csv2html the Pharo version
by Sven Van Caekenberghe
Hi,
Today I came across some bash code on a web page that loves Smalltalk, ah the horror ;-)
http://car.mines-douai.fr/2014/09/csv2html/
The goal is to make it easier to look at CSV data, for which a conversion to HTML was done. To just look at CSV data in a nice tabular form, we do not have to leave Pharo at all.
MultiColumnListModel new
items: (FileLocator desktop / 'test.csv' readStreamDo: [ :in |
(NeoCSVReader on: in) emptyFieldValue: ''; upToEnd ]);
displayBlock: [ :x | x ];
title: 'CSV Data';
openWithSpec.
Which results in this nice window:
To do a conversion to HTML, debugging the code in Pharo should be preferable to doing the same with bash & sed (for most of us anyway).
FileLocator desktop / 'csv.html' writeStreamDo: [ :out | | reader |
out << '<html><head><title>CSV Data</title></head><body><table border=1>'.
reader := NeoCSVReader on: (FileLocator desktop / 'test.csv') readStream.
reader emptyFieldValue: ''.
out << '<tr bgcolor=silver>'.
reader readHeader do: [ :each | out << '<th>'; << each; << '</th>' ].
out << '</tr>'.
reader do: [ :each |
out << '<tr>'.
each do: [ :td | out << '<td>'; << td; << '</td>' ].
out << '</table></body></html>'.
reader close ].
Which gives the following output:
NeoCSVReader is way more powerful in interpreting CSV files than a simple sed one-liner. Doing the same for a collection of files is easy. Maybe a little browser could even be written. Who knows, maybe Doru will add another tool to GT (TableViewer class>>#openStructuredOn: would do the trick I guess) ;-)
Sven
PS: The bash script was actually quite well written, even I could read/understand it. Thanks for sharing, it was the inspiration to do this little hack.
Sept. 18, 2014
Re: [Pharo-dev] Why Bloc?
by Alain Plantec
On 18 sept. 2014, at 04:44, Sean P. DeNigris <sean(a)clipperadams.com> wrote:
> stepharo wrote
>> - look at what he is doing
>> - we try to document the classes
>> ...
>
> How do I start playing with Bloc? After loading the development version into
> Pharo 3.0 and doing "BlMorphToTestMouseEnterLeave new openInWorld" I get
> "MessageNotUnderstood: receiver of "activeWorld" is nil"
Hi Sean,
Notice that you must run Bloc (be in a Bloc world) before you can run any of the bloc examples.
You can run Morphic within Bloc but not Bloc examples within a Morphic world.
first make sure that you have loaded the 4 Bloc-* packages.
then, (an issue that I must dig) if you image is a fresh one, make sure the author full name is well initialized with:
Author requestFullName
then you are ready to run a Bloc world:
world menu>Bloc>New Bloc space
world menu>Bloc>Switch to Bloc space...
choose 'Bloc-1'
Normally, you should switch to a new world (with a random background color).
The world menu is opened with the right mouse click (not the left one as in Morphic).
You can come back to Morphic by using world menu>Bloc>Switch to Bloc space...
Then you can try examples:
see class side of BlMorphWithLayout, BlPluggableEventListener, BlScheduledProcessingQueue
you can also try BlUniverse>>moveBlBigPasteUp (and compare it to BlUniverse>>moveBigPasteUp but within the Morphic world).
the same for BlMorphWithLayout>>moveMorphWithTableLayoutAnd10000Children versus
BlMorphWithLayout>>moveMorphWithTableLayoutAnd10000Children_morphic under Morphic.
Cheers
Alain
>
>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/Why-Bloc-tp4771757p4778711.html
> Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
>
Sept. 18, 2014
Re: [Pharo-dev] Why Bloc?
by Sean P. DeNigris
stepharo wrote
> - look at what he is doing
> - we try to document the classes
> ...
How do I start playing with Bloc? After loading the development version into
Pharo 3.0 and doing "BlMorphToTestMouseEnterLeave new openInWorld" I get
"MessageNotUnderstood: receiver of "activeWorld" is nil"
-----
Cheers,
Sean
--
View this message in context: http://forum.world.st/Why-Bloc-tp4771757p4778711.html
Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
Sept. 18, 2014
Re: [Pharo-dev] I'm confused about Process>>isTerminated
by Eliot Miranda
Hi Max,
On Wed, Sep 17, 2014 at 1:59 PM, Max Leske <maxleske(a)gmail.com> wrote:
> Hi Eliot
>
>
> On 16.09.2014, at 20:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
>
> Hi Max,
>
> On Tue, Sep 16, 2014 at 11:05 AM, Max Leske <maxleske(a)gmail.com> wrote:
>
>> Hi
>>
>> As always when I want to check if a process has died I get very confused
>> by #isTerminated and Iâm wondering if I just donât get how itâs supposed to
>> work or if there are others that share my confusion.
>>
>> Old implementation:
>>
>> isTerminated
>>
>> self isActiveProcess ifTrue: [^ false].
>> ^suspendedContext isNil
>> or: ["If the suspendedContext is the bottomContext it is the
>> block in Process>>newProcess.
>> If so, and the pc is greater than the startpc, the
>> bock has alrteady sent and returned
>> from value and there is nothing more to do."
>> suspendedContext isBottomContext
>> and: [ suspendedContext pc > suspendedContext startpc ] ]
>>
>>
>> Pharo 4 implementation:
>>
>> isTerminated
>> self isActiveProcess ifTrue: [^ false].
>> ^suspendedContext isNil
>> or: ["If the suspendedContext is the bottomContext it is the
>> block in Process>>newProcess.
>> If so, and the pc is greater than the startpc, the bock
>> has alrteady sent and returned
>> from value and there is nothing more to do.â
>> suspendedContext isBottomContext
>> and: [ suspendedContext isDead not
>> â<âââââââââââââââââââââââââ new"
>> and: [ suspendedContext pc > suspendedContext startpc ] ]
>> ]
>>
>>
>> The old implementation would break if the suspended context was dead
>> (i.e. the pc was nil) because the send of #> would produce an MNU.
>> The new implementation doesnât fix that, even though it looks like it at
>> first glance: if the pc is nil, the #> send will still happen -> MNU.
>>
>
> Off the top of my head it would seem that it should be isDead or: [] not
> isDead not and:
>
> isTerminated
> self isActiveProcess ifTrue: [^ false].
> ^suspendedContext isNil
> or: ["If the suspendedContext is the bottomContext it is the
> block in Process>>newProcess.
> If so, and the pc is greater than the startpc, the bock
> has alrteady sent and returned
> from value and there is nothing more to do.â
> suspendedContext isBottomContext
> and: [ suspendedContext isDead
> or: [ suspendedContext pc > suspendedContext
> startpc ] ] ]
>
>
> Phew. Glad you see that the same way.
>
> isDead
>> ^ pc isNil
>>
>
> and maybe (suspendedContext pc ifNil: [true] ifNotNil: [:pc| pc >
> suspendedContext startpc]) is more obvious.
>
> Anyway, neither implementation will reliably tell me if the process has
>> been terminated:
>> - an inactive process will be suspended when #terminate is sent and
>> report that it has not been terminated (#isSuspended -> true, #isTerminated
>> -> false)
>>
>
> except that it *hasn't* been terminated, it is merely in the process of
> termination. It isn't terminated until all unwind blocks have run, right?
>
>
> True. Easy to forget when you can just kill -9 on the console⦠:)
>
>
>
>> - a properly terminated process will raise an MNU (although apparently
>> not always�)
>>
>
> but that's a bug the change I suggested will fix.
>
>
>> - all the states in between: no clue
>>
>> I would like to know two things:
>> 1. how can I check if a process has already *received* a #terminate? (I
>> would then assume that the process will die eventually)
>>
>
> I don't think you can without putting a critical section around terminate
> and adding some process-specific variable that is set when you send
> terminate. termination is not instantaneous (unwind blocks have to be
> run), so it is potentially interruptible.
>
>
> Iâve thought about this a bit. I wouldnât really care if I donât get a
> correct answer about the termination status immediately but I want to have
> it before the process terminates. In case of something like the following:
>
> ([ 10 seconds asDelay wait ] forkAt: 11) terminate
>
> it can (potentially) take a very long time for the process to terminate.
> So if I have to poll 3 or 4 times thatâs ok but I donât want to wait for
> minutes.
> One solution would be to take your idea of the variable, but without the
> critical block:
>
> terminate
> "Stop the process that the receiver represents forever. Unwind to execute
> pending ensure:/ifCurtailed: blocks before terminating."
>
> | ctxt unwindBlock oldList |
> terminating := true. â<âââââââââââââââââââââââââââââââââââ changed"
> self isActiveProcess
> ifTrue: [
> ctxt := thisContext.
> [ ctxt := ctxt findNextUnwindContextUpTo: nil.
> ctxt isNil ] whileFalse:
> [ (ctxt tempAt: 2) ifNil:
> [ ctxt tempAt: 2 put: nil.
> unwindBlock := ctxt tempAt: 1.
> thisContext terminateTo: ctxt.
> unwindBlock value ]].
> thisContext terminateTo: nil.
> self suspend ]
> ifFalse: [
> "Always suspend the process first so it doesn't accidentally get woken up"
> oldList := self suspend.
> suspendedContext ifNotNil:[
> "Figure out if we are terminating the process while waiting in
> Semaphore>>critical:
> In this case, pop the suspendedContext so that we leave the ensure: block
> inside
> Semaphore>>critical: without signaling the semaphore."
> (oldList class == Semaphore and:[
> suspendedContext method == (Semaphore compiledMethodAt: #critical:)])
> ifTrue:[
> suspendedContext := suspendedContext home.].
> "If we are terminating a process halfways through an unwind, try to
> complete that unwind block first."
> (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [ :outer |
> (suspendedContext findContextSuchThat: [ :c | c closure == (outer tempAt:
> 1)])
> ifNotNil: [ :inner |
> "This is an unwind block currently under evaluation"
> suspendedContext runUntilErrorOrReturnFrom: inner ]].
> ctxt := self popTo: suspendedContext bottomContext.
> ctxt == suspendedContext bottomContext ifFalse: [
> self debug: ctxt title: 'Unwind error during termination']] ].
>
>
>
> isTerminating
> ^ terminating ifNil: [ ^ false ]
>
>
> With this small modification I can run the example from above and
> immediately see that it will die eventually.
>
> Iâm aware that one process might not see the change to the variable
> immediately but as I said, I wouldnât really care.
>
>
> What do you think?
>
Yes that looks good. But given that branches are atomic (ifTrue: is not a
send) why not do
Process>>initialize
terminating := false.
terminate
"Stop the process that the receiver represents forever. Unwind to execute
pending ensure:/ifCurtailed: blocks before terminating."
| ctxt unwindBlock oldList |
terminating
ifTrue: [self error: 'Process is already terminated, or being terminated']
ifFalse: [terminating := true].
self isActiveProcess
ifTrue:
...
?
I would suggest a status inst var, as in
Process>>initialize
status := nil
terminate
"Stop the process that the receiver represents forever. Unwind to execute
pending ensure:/ifCurtailed: blocks before terminating."
| ctxt unwindBlock oldList |
status == #terminating
ifTrue: [self error: 'Process is already terminated, or being terminated']
ifFalse: [status := terminating].
self isActiveProcess
ifTrue:
...
but the temptation then is to have lots of different status values and I'm
leery of introducing that kind of complication without a strong
justification.
> Cheers,
> Max
>
>
>
>> 2. how can I check if a process is *actually* dead? (in case a âhalf
>> deadâ process will still unwind or whatever)
>>
>
> see above.
>
>
>>
>> What would be necessary to make those tests (or better ones) possible
>> (rewrite the whole process implementation?)?
>>
>>
>> Cheers,
>> Max
>>
>
> --
> best,
> Eliot
>
>
--
best,
Eliot
Sept. 17, 2014
Re: [Pharo-dev] I'm confused about Process>>isTerminated
by Max Leske
Hi Eliot
On 16.09.2014, at 20:18, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
> Hi Max,
>
> On Tue, Sep 16, 2014 at 11:05 AM, Max Leske <maxleske(a)gmail.com> wrote:
> Hi
>
> As always when I want to check if a process has died I get very confused by #isTerminated and Iâm wondering if I just donât get how itâs supposed to work or if there are others that share my confusion.
>
> Old implementation:
>
> isTerminated
>
> self isActiveProcess ifTrue: [^ false].
> ^suspendedContext isNil
> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
> from value and there is nothing more to do."
> suspendedContext isBottomContext
> and: [ suspendedContext pc > suspendedContext startpc ] ]
>
>
> Pharo 4 implementation:
>
> isTerminated
> self isActiveProcess ifTrue: [^ false].
> ^suspendedContext isNil
> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
> from value and there is nothing more to do.â
> suspendedContext isBottomContext
> and: [ suspendedContext isDead not â<âââââââââââââââââââââââââ new"
> and: [ suspendedContext pc > suspendedContext startpc ] ] ]
>
>
> The old implementation would break if the suspended context was dead (i.e. the pc was nil) because the send of #> would produce an MNU.
> The new implementation doesnât fix that, even though it looks like it at first glance: if the pc is nil, the #> send will still happen -> MNU.
>
> Off the top of my head it would seem that it should be isDead or: [] not isDead not and:
>
> isTerminated
> self isActiveProcess ifTrue: [^ false].
> ^suspendedContext isNil
> or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess.
> If so, and the pc is greater than the startpc, the bock has alrteady sent and returned
> from value and there is nothing more to do.â
> suspendedContext isBottomContext
> and: [ suspendedContext isDead
> or: [ suspendedContext pc > suspendedContext startpc ] ] ]
Phew. Glad you see that the same way.
> isDead
> ^ pc isNil
>
> and maybe (suspendedContext pc ifNil: [true] ifNotNil: [:pc| pc > suspendedContext startpc]) is more obvious.
>
> Anyway, neither implementation will reliably tell me if the process has been terminated:
> - an inactive process will be suspended when #terminate is sent and report that it has not been terminated (#isSuspended -> true, #isTerminated -> false)
>
> except that it *hasn't* been terminated, it is merely in the process of termination. It isn't terminated until all unwind blocks have run, right?
True. Easy to forget when you can just kill -9 on the console⦠:)
>
> - a properly terminated process will raise an MNU (although apparently not always�)
>
> but that's a bug the change I suggested will fix.
>
> - all the states in between: no clue
>
> I would like to know two things:
> 1. how can I check if a process has already *received* a #terminate? (I would then assume that the process will die eventually)
>
> I don't think you can without putting a critical section around terminate and adding some process-specific variable that is set when you send terminate. termination is not instantaneous (unwind blocks have to be run), so it is potentially interruptible.
Iâve thought about this a bit. I wouldnât really care if I donât get a correct answer about the termination status immediately but I want to have it before the process terminates. In case of something like the following:
([ 10 seconds asDelay wait ] forkAt: 11) terminate
it can (potentially) take a very long time for the process to terminate. So if I have to poll 3 or 4 times thatâs ok but I donât want to wait for minutes.
One solution would be to take your idea of the variable, but without the critical block:
terminate
"Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating."
| ctxt unwindBlock oldList |
terminating := true. â<âââââââââââââââââââââââââââââââââââ changed"
self isActiveProcess
ifTrue: [
ctxt := thisContext.
[ ctxt := ctxt findNextUnwindContextUpTo: nil.
ctxt isNil ] whileFalse:
[ (ctxt tempAt: 2) ifNil:
[ ctxt tempAt: 2 put: nil.
unwindBlock := ctxt tempAt: 1.
thisContext terminateTo: ctxt.
unwindBlock value ]].
thisContext terminateTo: nil.
self suspend ]
ifFalse: [
"Always suspend the process first so it doesn't accidentally get woken up"
oldList := self suspend.
suspendedContext ifNotNil:[
"Figure out if we are terminating the process while waiting in Semaphore>>critical:
In this case, pop the suspendedContext so that we leave the ensure: block inside
Semaphore>>critical: without signaling the semaphore."
(oldList class == Semaphore and:[
suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[
suspendedContext := suspendedContext home.].
"If we are terminating a process halfways through an unwind, try to complete that unwind block first."
(suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: [ :outer |
(suspendedContext findContextSuchThat: [ :c | c closure == (outer tempAt: 1)])
ifNotNil: [ :inner |
"This is an unwind block currently under evaluation"
suspendedContext runUntilErrorOrReturnFrom: inner ]].
ctxt := self popTo: suspendedContext bottomContext.
ctxt == suspendedContext bottomContext ifFalse: [
self debug: ctxt title: 'Unwind error during termination']] ].
isTerminating
^ terminating ifNil: [ ^ false ]
With this small modification I can run the example from above and immediately see that it will die eventually.
Iâm aware that one process might not see the change to the variable immediately but as I said, I wouldnât really care.
What do you think?
Cheers,
Max
>
> 2. how can I check if a process is *actually* dead? (in case a âhalf deadâ process will still unwind or whatever)
>
> see above.
>
>
> What would be necessary to make those tests (or better ones) possible (rewrite the whole process implementation?)?
>
>
> Cheers,
> Max
>
>
>
> --
> best,
> Eliot
Sept. 17, 2014
[Review: 12111] (Date readFrom: '4.2.2013' readStream pattern: 'd.m.yy') ==>> 4 February 2020
by Max Leske
In the spirit of Markusâ cleanup please review this suggested fix to date parsing (from november 2013 originallyâ¦). Iâve ported the fix forward to 40 (which has the same issue).
https://pharo.fogbugz.com/f/cases/12111/Date-readFrom-4-2-2013-readStream-p…
Cheers,
Max
Sept. 17, 2014