Erlang/ets: reset ets table after getting a “bad argument”?

随声附和 提交于 2019-12-19 08:11:03

问题


I've been learning how to use ets, but one thing that has bothered me is that, occasionally*, ets:match throws a bad argument… And, from them on, all subsequent calls (even calls which previously worked) also throw a bad argument:

> ets:match(Tid, { [$r | '$1'] }, 1).
% this match works...
% Then, at some point, this comes up:
** exception error: bad argument
     in function  ets:match/3
        called as ets:match(24589,{[114|'$1']},1)
% And from then on, matches stop working:
> ets:match(Tid, { [$r | '$1'] }, 1).
** exception error: bad argument
     in function  ets:match/3
        called as ets:match(24589,{[114|'$1']},1)

Is there any way to "reset" the ets system so that I can query it (ie, from the shell) again?

*: I haven't been able to reproduce the problem… But it happens fairly often while I'm trying to do "other things".


回答1:


Although I'm not 100% sure, this thread seems to answer your question. It appears that you're observing this behaviour in the shell. If so, two facts are interacting in a confusing way:

  1. An ets table is deleted as soon as its owning process dies.
  2. The erlang shell dies whenver it receives an exception and is silently restarted.

So, when you get the first exception, the current shell process dies causing the ets table to be deleted, and then a new shell process is started for you. Now, when you try another ets:match, it fails because the table no longer exists.




回答2:


Dale already told you what happens. You can confirm that by calling self() in the shell every now and then.

As a quick workaround you can spawn another process to create a public table for you. Then that table won't die along with your shell.

1> self().
<0.32.0>    % shell's Pid

2> spawn(fun() -> ets:new(my_table, [named_table, public]), receive X -> ok end end).
<0.35.0>    % the spawned process's Pid

3> ets:insert(my_table, {a, b}).
true

Now make an exception and check that the table indeed survived.

4> 1/0.
** exception error: bad argument in an arithmetic expression
     in operator  '/'/2
        called as 1 / 0
5> self().
<0.38.0>   % shell's reborn, with a different Pid

6> ets:insert(my_table, {c, d}).
true
7> ets:tab2list(my_table).
[{c,d},{a,b}]    % table did survive the shell restart

To delete the table, just send something to your spawned process:

8> pid(0,35,0) ! bye_bye.
bye_bye
9> ets:info(my_table).   
undefined


来源:https://stackoverflow.com/questions/1964990/erlang-ets-reset-ets-table-after-getting-a-bad-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!