开发者

Erlang: Why can't I register self()?

This line fails with a badarg exception:

register(myproc, self()),

开发者_StackOverflow社区The documentation says that self/0 returns a pid and that register/2 takes a pid. So what gives?

Edit: No, seriously, it's not already registered, it's not a reserved atom, and it works when I register it from the process that's spawning it.

Oh weird! Okay, I got some more clues. When I move the call to register() around to different places, sometimes it works and sometimes it breaks. Here's my sample code. Run it before you call me crazy. :-)

-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]).


If the process is already registered, it will throw a badarg. There is also some other cases that causes this, like the name is already used. See the erlang:register/2 docs for more.

EDIT

It's great that you posted code to reproduce your problem.

So, the first time you enter pongr/0 you will register self(). When you receive a message, you will process it and call pongr/0 again. The second time you enter pongr/0 you try to register self(), which fails because it's already registered.

Also, if you want to use register a large number of processes, you should look into gproc. register/2 requires an atom as the key and there is a limit of around one million atoms, unless you explicitly change it. See the efficiency guide. gproc can also run distributed and may thus be used instead of the global module.


is myproc already registered?

first call should succeed, additional calls will cause badarg exception.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜