[Pharo-project] [squeak-dev] Re: Process-specific state broken and uncomplete

Igor Stasenko siguctua at gmail.com
Tue Nov 9 05:18:13 CET 2010


On 9 November 2010 05:59, Levente Uzonyi <leves at elte.hu> wrote:
> On Tue, 9 Nov 2010, Igor Stasenko wrote:
>
> snip
>
>> Suppose you have a domain object which provides following ways to
>> access the session:
>>
>> session: forkedSession
>>   Processor activeProcess environmentAt: #session put: forkedSession
>>
>> session
>>   ^ Processor activeProcess environmentAt: #session
>>
>>
>> now, here what i'd like to write:
>>
>> | session |
>>
>> session := MySession new .
>> session initialize blabla.
>>
>> "good fork"
>> good := [
>>  self session: session.
>>  [ self process stuff ] ensure: [ session close ]
>> ] newProcess.
>>
>> good resume.
>> 1 minute asDelay wait.
>> good terminate.
>> self assert: (session isClosed).
>>
>> In the above case, everything is ok: session object is passed in 'session'
>> temp
>> and visible inside ensure block directly, so, no matter what may
>> happen (process termination),
>> it is guaranteed that session will be closed at the end.
>>
>> "bad fork"
>>
>> session := MySession new .
>> session initialize blabla.
>>
>> bad := [
>>  self session: session.
>>  [ self process stuff ] ensure: [ self session close ]
>> ] newProcess.
>>
>> bad resume.
>> 1 minute asDelay wait.
>> bad terminate.
>> self assert: (session isClosed).
>>
>>
>> In this case, a session is accessed indirectly, through process specific
>> state.
>> And test might fail or not, depending if process was already
>> terminated before sending #terminate,
>> or its still running.
>>
>> The 'bad fork' illustrates that one should not attempt to access a
>> process specific state in ensure blocks,
>> because during process termination, stack unwinding is performed by
>> other process, which could have different session object,
>> or don't have it at all.
>>
>> This is simple, of course, to implement session finalization without
>> using process spefic state. But now consider that session has not only
>> #close method, but allows doing something more userful, like:
>>
>> self session backupStuff.
>> [   .. do something.. ] ensure: [ self session restoreStuff ].
>>
>> And again, same problem: unless you have a direct reference to session
>> object, you can't do it.
>> Not with using process-specific state, because it is flawed.
>>
>> In other words, anything which may want to access to a
>> process-specific state, like:
>>
>> [ ... ... ] ensure: [ (Processor activeProcess environmentAt: #foo)
>> doSomething ]
>>
>> have no guarantees to work correctly in all cases.
>>
>> This defeats a purpose of process-specific state, because you can't
>> rely on it for building a reliable stuff.
>
> Not really. You can store the sessions in a session store which is
> responsible for retrieving the session:
>
> [
>        sessionStore useSession: sessionKey during: [ :session |
>                Processor activeProcess environmentAt: #session put: session.
>                self doSomething.
>                Processor activeProcess environmentAt: #session put: nil ] ]
> fork.
>
> SessionStore >> useSession: sessionKey during: aBlock
>
>        | session |
>        [
>                session := self sessionFor: sessionKey.
>                aBlock value: session ]
>                ensure: [
>                        session ifNotNil: [
>                                self releaseSession: session ] ]
>
> In #doSomething you can access the session via the process. We're using this
> pattern in PostgresV3's connection pool. It works pretty well.
>

No, you can't. I feel sorry for you :)

A #useSession:during: using ensure, and of course it will work
correctly, because you not accessing session via
process-specific storage. This is illustrated by my "good fork" example.

now replace #doSomething with this:

[ 1 year asDelay wait ] ensure: [
  self assert:  (Processor activeProcess environmentAt: #session) notNil ]

and then terminate a process which running your fork.

In attachment you'll find a test, which shows the problem (i using
tests from Pharo image).


>
> Levente
>
>
> snip
>
>



-- 
Best regards,
Igor Stasenko AKA sig.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ProcessSpecificTest-testLocalVariableInEnsureBlock.st
Type: application/octet-stream
Size: 505 bytes
Desc: not available
URL: <http://lists.gforge.inria.fr/pipermail/pharo-project/attachments/20101109/eeef9058/attachment.obj>


More information about the Pharo-project mailing list