[erlang-questions] non-FIFO behavior in process mailboxes?

Michael Turner <>
Mon Apr 23 05:38:28 CEST 2012


On Mon, Apr 23, 2012 at 2:23 AM, Ulf Wiger <> wrote:
> You seem to have a race between the messages sent from the client and the ones the server sends to itself.

That, I could see. What I couldn't see was how. But it came to me when
my head hit the pillow. (Which was, naturally, shortly after I sent
e-mail to the list about it.) Sometimes, when I'm tired, I fall into
an old mindset that apparently derives from the days of writing
interrupt service routines running at high processor priority back in
the 1980s. And even *that's* not a good excuse in this case.

> Bear in mind that the client doesn't yield after send, add SMP to the mix and you cannot know whether that server consumes the first message before the client sends its
>
> BR,

Before the client sends its ... BR? "Best Regards"? After a delay? Oh,
*that's* what I forgot to do! ;-)

This bug came out of experimentation inspired by the recent discussion
of initializing objects *after* their creation, a topic raised by
Richard O'Keefe. And -- waddya know -- the problem here relates
directly to his objection to this practice: inconsistent intermediate
states. It appears that when you model your objects as processes, the
danger is particularly acute.

Lesson learned. Message ... received.

-michael turner

> 22 apr 2012 kl. 18:25 skrev Michael Turner <>:
>
>> When the code listed below executes with the first io:format call
>> commented out, it breaks, reporting:
>>
>> ** exception error: no match of right hand side value []
>>     in function  wg:init/0
>>
>> When I don't have it commented out, it works (sort of), writing
>>
>>  val_for (P)=[]
>>  val_for (P)=2
>>  ok
>>
>> Here's the code:
>> -----
>>
>> -module(wg).
>> -export ([init/0, be/2]).
>>
>> val_for (P) ->
>>    P ! {tell, self(), val},
>>    receive
>>        {Val, for, P} -> Val
>>    end.
>>
>> be (Arg, Val) ->
>>    receive
>>        [H|T] ->
>>            self() ! T,
>>            self() ! H,
>>            be (Arg, Val);
>>        [] ->
>>            be (Arg, Val);
>>        {tell, X, val} ->
>>            X ! {Val, for, self()},
>>            be (Arg, Val);
>>        {set_arg_to, A} ->
>>            be (A, Val);
>>        {set_val_to, V} ->
>>            be (Arg, V)
>>    end.
>>
>> init() ->
>>    P = spawn (wg, be, [[],[]]),
>>    P ! [{set_arg_to, 1}, {set_val_to, 2}],
>> %   io:format ("val_for (P)=~p~n", [val_for (P)]),
>>    2 = val_for (P),
>>    io:format ("val_for (P)=~p~n", [val_for (P)]),
>>    ok.
>> -----
>>
>> This is R14B on Windows XP. Haven't tried it elsewhere yet.
>>
>> Seeing this really messes with my mental model of process mailboxes.
>> With the first io:format call commented out, I think process P should
>> be seeing messages queued up in the following order:
>>
>>  [{set_arg_to, 1}, {set_val_to, 2}]
>>  [{set_val_to, 2}]
>>  {set_arg_to, 1}
>>  []
>>  {set_val_to, 2}
>>  {tell, X, val}
>>
>> And shouldn't this mean that Val = 2 in process P when the {tell, X,
>> val} message reaches P? As I interpret Armstrong pp.145-6, since
>> matches are guaranteed in this case, there's no save queue activity;
>> since there's no "after" close, the timer is irrelevant; so you should
>> get pure FIFO behavior, right?
>>
>> -michael turner
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list