Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  Concurrency problem

luke at not-a-domain.com
Posted: Wed Aug 04, 1999 7:36 pm Reply with quote
Guest
Hi all,

I'm wondering if someone can help me with a pattern for avoiding a
deadlock. Fundamentally, my problem is this:

I have two gen_server processes, A and B. A wants to make a call on
B for the sake of the side-effects. These side-effects involve making
calls to A.

So, it seems to me that if A makes a gen_server:call to B, then when B
does the same back to A, it will get a cycle in the call graph and
deadlock. Now, it might seem that it's the inappropriate use of
side-effects that's the problem, and that B should just return a value
for A to use, however I'm trying to follow an explicit mapping which
has things this way. Specifically, a corba Portable Object Adapter
calling an AdapterActivator.

Any help would be appreciated. Infact, I'd love to some general
information about managing things with Erlang's concurrency model, I'm
sure there are oodles of useful patterns - pointers would be great!

Cheers,
Luke




Post generated using Mail2Forum (http://m2f.sourceforge.net)
tobbe at serc.rmit.edu.au
Posted: Thu Aug 05, 1999 2:01 am Reply with quote
Guest
> So, it seems to me that if A makes a gen_server:call to B, then when B
> does the same back to A, it will get a cycle in the call graph and
> deadlock.

Yes, and to avoid that you can either:

1. Use gen_server:cast/2 .
2. Spawn of a new process P which does the the gen_server:/call
to B, and then relay the answer back to A.

In both cases you have to be make sure you can receive those
messages (from P and B) in A.

Cheers /Tobbe


Post generated using Mail2Forum (http://m2f.sourceforge.net)
Pekka.Hedqvist at ericsso
Posted: Thu Aug 05, 1999 3:43 am Reply with quote
Guest
And in some cases it can be convenient to use the
'gen_server:reply(To, Reply)' call in a handle_call
instead to make an explicit reply to the caller and
then go on doing something..

Torbjorn Tornkvist writes:
>
> > So, it seems to me that if A makes a gen_server:call to B, then when B
> > does the same back to A, it will get a cycle in the call graph and
> > deadlock.
>
> Yes, and to avoid that you can either:
>
> 1. Use gen_server:cast/2 .
> 2. Spawn of a new process P which does the the gen_server:/call
> to B, and then relay the answer back to A.
>
> In both cases you have to be make sure you can receive those
> messages (from P and B) in A.
>
> Cheers /Tobbe
>


Post generated using Mail2Forum (http://m2f.sourceforge.net)
klacke at bluetail.com
Posted: Thu Aug 05, 1999 8:28 am Reply with quote
Guest
> I'm wondering if someone can help me with a pattern for avoiding a
> deadlock. Fundamentally, my problem is this:
>
> I have two gen_server processes, A and B. A wants to make a call on
> B for the sake of the side-effects. These side-effects involve making
> calls to A.
>

This is a classic situation, I've encoutered the
same problem over and over again. Mnesia is for example
full with code that really would like to make a simple
gen_server:call to the remote side but can't do it since the
other side would then do the same.

You need to do some sort of async solution here.

1. Send request. (gen_server:cast)
2. Mark request as outstanding, (change server state)
3. When reply comes handle it as usual.

A bit irritating since this is such a common situation.

Cheers

/klacke



Post generated using Mail2Forum (http://m2f.sourceforge.net)
luke at not-a-domain.com
Posted: Sat Aug 07, 1999 7:52 pm Reply with quote
Guest
Klacke <klacke_at_bluetail.com> writes:

> > I'm wondering if someone can help me with a pattern for avoiding a
> > deadlock. Fundamentally, my problem is this:
> >
> > I have two gen_server processes, A and B. A wants to make a call on
> > B for the sake of the side-effects. These side-effects involve making
> > calls to A.
> >
>
> This is a classic situation, I've encoutered the
> same problem over and over again. Mnesia is for example
> full with code that really would like to make a simple
> gen_server:call to the remote side but can't do it since the
> other side would then do the same.
>
> You need to do some sort of async solution here.
>
> 1. Send request. (gen_server:cast)
> 2. Mark request as outstanding, (change server state)
> 3. When reply comes handle it as usual.
>
> A bit irritating since this is such a common situation.

Thanks for the advice (and Tobbe and Pekka too). I've had a quick
look at these parts of the Mnesia source and it's obvious there's
something for me to learn there.

I'd also really like to learn some more general rules for this sort of
thing. It seems that there should be useful design patterns for
structuring the concurrency safely. Could anyone point me at some
documentation for this? Infact, I'd like to read any documentation
that's related to erlang and can't be easily found on the website.

Something that particularly caught my eye was an abstract for a talk
Joe Armstrong gave that I found on the web, titled "Higher order
processes in Erlang". Is there somewhere I could grab a paper
covering this material or some like it?

Cheers,
Luke




Post generated using Mail2Forum (http://m2f.sourceforge.net)
ulf.wiger at etxb.ericsso
Posted: Sun Aug 08, 1999 5:06 pm Reply with quote
Guest
One solution that I sometimes use is to store state data in ETS.
Say, for example (don't know if this fits your particular problem) that
A wants to make a "write" request to B, and B in the process wants to make
a "read" request to A, this can be solved by A storing readable values
in a public or protected ETS table. This way, B can make a non-blocking
request and avoid deadlock.

To avoid creating a race condition instead, one should take case not to
write to the ETS table from more than one process.

/Uffe

On 5 Aug 1999, Luke Gorrie wrote:

luke>Hi all,
luke>
luke>I'm wondering if someone can help me with a pattern for avoiding a
luke>deadlock. Fundamentally, my problem is this:
luke>
luke>I have two gen_server processes, A and B. A wants to make a call on
luke>B for the sake of the side-effects. These side-effects involve making
luke>calls to A.
luke>
luke>So, it seems to me that if A makes a gen_server:call to B, then when B
luke>does the same back to A, it will get a cycle in the call graph and
luke>deadlock. Now, it might seem that it's the inappropriate use of
luke>side-effects that's the problem, and that B should just return a value
luke>for A to use, however I'm trying to follow an explicit mapping which
luke>has things this way. Specifically, a corba Portable Object Adapter
luke>calling an AdapterActivator.
luke>
luke>Any help would be appreciated. Infact, I'd love to some general
luke>information about managing things with Erlang's concurrency model, I'm
luke>sure there are oodles of useful patterns - pointers would be great!
luke>
luke>Cheers,
luke>Luke
luke>
luke>
luke>

Ulf Wiger, Chief Designer AXD 301 <ulf.wiger_at_etx.ericsson.se>
Ericsson Telecom AB tfn: +46 8 719 81 95
Varuv

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum