4
votes

I have a strange behaviour in erlang with ets:select.

I achieve a correct select statement (4 and 5 below), then I make an error in my statement (6 below), and then I try again the same statement as in 4 and 5, and it does not work any longer.

What is happening ? any idea ?

Erlang R14B01 (erts-5.8.2) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.8.2  (abort with ^G)
1> Tab = ets:new(x, [private]).
16400
2> ets:insert(Tab, {c, "rhino"}).
true
3> ets:insert(Tab, {a, "lion"}). 
true
4> ets:select(Tab,[{{'$1','$2'},[],['$1', '$2']}]).      
["rhino","lion"]    
5> ets:select(Tab,[{{'$1','$2'},[],['$1', '$2']}]).      
["rhino","lion"]
6> ets:select(Tab,[{{'$1','$2'},[],['$1', '$2', '$3']}]).
** exception error: bad argument
 in function  ets:select/2
    called as ets:select(16400,[{{'$1','$2'},[],['$1','$2','$3']}])
7> ets:select(Tab,[{{'$1','$2'},[],['$1', '$2']}]).      
** exception error: bad argument
 in function  ets:select/2
    called as ets:select(16400,[{{'$1','$2'},[],['$1','$2']}])

Has my ets table been destroyed ? Would it be a bug of ets ?

Thank you.

2

2 Answers

6
votes

The shell process has created the ETS table and is the owner of it. When the owner process dies the ETS table is automatically deleted.

So when you get an exception at 6, the shell process dies so the ETS table is deleted.

Making it private also means that no other process can access it (so even if the table was persisted the new shell wouldn't be able to access it), but in this case it is even worse as the table has been deleted.

3
votes

(too big to leave as a comment to thanosQR's correct answer)

if you'd like the table to survive an exception in the shell, you can give it away to another process. for example:

1> Pid = spawn(fun () -> receive foo -> ok end end).    % sit and wait for 'foo' message
<0.62.0>
2> Tab = ets:new(x, [public]).                          % Tab must be public if you plan to give it away and still have access
24593
3> ets:give_away(Tab, Pid, []).
true
4> ets:insert(Tab, {a,1}).
true
5> ets:tab2list(Tab).
[{a,1}]
6> 3=4.
** exception error: no match of right hand side value 4
7> ets:tab2list(Tab).                                   % Tab survives exception
[{a,1}]
8> Pid ! foo.                                           % cause owning process to exit
foo
9> ets:tab2list(Tab).                                   % Tab is now gone
** exception error: bad argument
     in function  ets:match_object/2
        called as ets:match_object(24593,'_')
     in call from ets:tab2list/1 (ets.erl, line 323)