[erlang-bugs] mnesia:read returns undefined when getting write lock when sticky_write lock is held

Magnus Henoch <>
Thu Dec 1 18:24:30 CET 2011


Hi all,

I noticed that mnesia:read would return the atom undefined instead of
a list of records in some cases, and managed to reduce it to the test
case below, which triggers the error in both R14B01 and R15A.

This seems to happen when one node holds a sticky lock on a table, and
another node calls mnesia:read(Table, Key, write), i.e. reading while
getting a write lock.  (It wasn't intentional, I was in the process of
removing sticky locks and had forgotten one place.)

This test case:

-module(foo).

-include_lib("eunit/include/eunit.hrl").

-export([foo/0]).

foo() ->
    net_kernel:start([, shortnames]),
    {ok, Slave} = slave:start_link(localhost, slave),
    mnesia:start(),
    try
        ?assertEqual(ok, rpc:call(Slave, mnesia, start, [])),
        ?assertMatch({ok, _}, mnesia:change_config(extra_db_nodes, [Slave])),
        ?debugVal(mnesia:create_table(foo, [{ram_copies, [node(), Slave]}])),
        ?assertEqual(ok, rpc:call(Slave, mnesia, wait_for_tables, [[foo], 1000])),
        ?assertEqual({atomic, ok},
                     ?debugVal(
                        mnesia:transaction(
                          fun() ->
                                  mnesia:write(foo, {foo, 42, a}, sticky_write)
                          end))),
        ?assertEqual({atomic, [{foo, 42, a}]},
                     ?debugVal(
                        rpc:call(
                          Slave, mnesia, transaction,
                          [fun mnesia:read/3, [foo, 42, write]])))
    after
        mnesia:stop(),
        mnesia:delete_schema([node(), Slave]),
        slave:stop(Slave)
    end.

produces this output:

Erlang R15A (erts-5.9.pre) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.pre  (abort with ^G)
1> foo:foo().
foo.erl:14:<0.32.0>: mnesia : create_table ( foo , [ { ram_copies , [ node ( ) , Slave ] } ] ) = {atomic,
                                                                             ok}
foo.erl:17:<0.32.0>: mnesia : transaction ( fun ( ) -> mnesia : write ( foo , { foo , 42 , a } , sticky_write ) end ) = {atomic,
                                                                                                    ok}
foo.erl:23:<0.32.0>: rpc : call ( Slave , mnesia , transaction , [ fun mnesia : read / 3 , [ foo , 42 , write ] ] ) = {atomic,
                                                                                                  undefined}

=INFO REPORT==== 1-Dec-2011::17:22:22 ===
    application: mnesia
    exited: stopped
    type: temporary
** exception error: {assertEqual_failed,[{module,foo},
                                         {line,26},
                                         {expression,"? debugVal ( rpc : call ( Slave , mnesia , transaction , [ fun mnesia : read / 3 , [ foo , 42 , write ] ] ) )"},
                                         {expected,{atomic,[{foo,42,a}]}},
                                         {value,{atomic,undefined}}]}
     in function  foo:'-foo/0-fun-8-'/2 (foo.erl, line 26)
     in call from foo:foo/0 (foo.erl, line 22)


-- 
Magnus Henoch
Erlang Solutions Ltd
http://www.erlang-solutions.com/



More information about the erlang-bugs mailing list