2011-03-17 100 views
0

这条线失败,并badarg例外:Erlang:为什么我不能注册self()?

register(myproc, self()), 

文档说self/0返回一个PID和register/2需要一个pid。那么是什么给了?

编辑:不,严重的是,它还没有被注册,它不是​​一个保留的原子,并且当我从产生它的进程中注册它时,它工作。

哦,太奇怪了!好的,我有更多的线索。当我将呼叫转移到register()到不同的地方时,有时它会起作用,有时会中断。这是我的示例代码。在你叫我疯狂之前运行它。 :-)

-module(pingpong). 
-export([start/1, ping/2, pong/0]). 

ping(N, Pong_Pid) -> 
    link(Pong_Pid), 
    pingr(N, Pong_Pid). 

pingr(0, _) -> 
    io:format("Ping exiting~n", []), 
    exit(ping); 

pingr(N, Pong_Pid) -> 
    Pong_Pid ! {ping, self()}, 
    receive 
     pong -> 
      io:format("Ping received pong~n", []) 
    end, 
    pingr(N - 1, Pong_Pid). 

pong() -> 
    %% This one works. 
    %%register(pong, self()), 
    process_flag(trap_exit, true), 
    pongr(). 

pongr() -> 
    %% This one fails. 
    register(pong, self()), 
    receive 
     {ping, Ping_PID} -> 
      io:format("Pong received ping~n", []), 
      Ping_PID ! pong, 
      pongr(); 
     {'EXIT', From, Reason} -> 
      io:format("pong exiting, got ~p~n", [{'EXIT', From, Reason}]) 
    end. 

start(Ping_Node) -> 
    PongPID = spawn(pingpong, pong, []), 
    spawn(Ping_Node, pingpong, ping, [3, PongPID]). 

回答

5

如果进程已经注册,它会抛出一个badarg。还有一些导致这种情况的其他情况,如名称已被使用。有关更多信息,请参见the erlang:register/2 docs

编辑

很棒,您发布代码来重现您的问题。

所以,你进入pongr/0你第一次将注册self()。当您收到一条消息时,您将处理该消息并再次致电pongr/0。你进入第二次pongr/0您尝试注册self(),因为它已经登记在哪个失败。

另外,如果你想使用注册了大量的进程,你应该看看gprocregister/2需要一个原子作为重点和有大约一百万个原子的限制,除非你明确地改变它。请参阅efficiency guidegproc也可以运行分布式,因此可以用来代替global模块。

+0

如果我没有先阅读文档,我不会来。 – 2011-03-17 21:26:53

+0

对不起,我不是故意要冒犯你。请参阅我编辑的答案,了解代码中的问题说明。 – knutin 2011-03-17 22:32:19

+0

Ohhhhhh,DUH !!!我几乎尴尬,我以前没有看到它。此外,谢谢你的奖金提示和效率链接。 – 2011-03-18 03:22:41

5

是myproc已经注册了吗?

第一次调用应该成功,额外的调用将导致badarg异常。

1> register(myproc, self()). 
true 
2> myproc ! foo. 
foo 
3> flush(). 
Shell got foo 
ok 
4> register(myproc, self()). 
** exception error: bad argument 
    in function register/2 
     called as register(myproc,<0.30.0>) 
+0

不,我知道那个问题了。 – 2011-03-17 21:26:03

相关问题