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

Levente Uzonyi leves at elte.hu
Tue Nov 9 03:59:05 UTC 2010


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.


Levente


snip



More information about the Squeak-dev mailing list