Transitive rpc call between nodes connected in chain

Let’s assume I have the following Erlang nodes architecture

A <-> B <-> C
  • A is connected to B
  • B is connected to C
  • A IS NOT connected to C

Why the following RPC call from A to B to C fails?

% we are on node A
rpc:call('b@myhost', rpc, call, [c@myhost', io, format, ["Node: ~w~n", [node()]]])

The error is

(a@myhost)1> net_kernel:connect_node('b@myhost').
true
(a@myhost)2> rpc:call('b@myhost', rpc, call, ['c@myhost', io, format, ["Node: ~w~n", [node()]]]).
{badrpc, {'EXIT',{terminated,[{io,format,
                                  ["Node: ~w~n",[a@myhost]],
                                  [{file, "io.erl"},
                                   {line,198},
                                   {error_info,#{cause => {io, terminated},
                                                 module => erl_stdlib_errors}}]}]}}}

Nodes are started with the following command

erl -sname a -connect_all false -kernel dist_auto_connect never -setcookie cookie

it fails because C can not send messages to the group leader (which is on A).

1.

rpc:call('b@myhost', rpc, call, [c@myhost, io, format, [standard_error, "Node: ~w~n", [node()]]]).

will work (and print output on node C’s standard error)

2.
rpc:call('b@myhost', rpc, call, [c@myhost, io, format, [standard_io, "Node: ~w~n", [node()]]]).

fails

3.
rpc:call('b@myhost', rpc, call, [c@myhost, io, format, [group_leader(), "Node: ~w~n", [node()]]]).

fails

4.
rpc:call('b@myhost', rpc, call, [c@myhost, io, format, ["Node: ~w~n", [node()]]]).

fails

2, 3 and 4 are failing for the same reason (C can not send messages to processes on A) because io:format/3 with standard_io as 1st argument is the same thing as io:format/3 with group_leader() as 1st argument, and that is equivalent to io:format/2

now why does rpc:call('b@myhost', io, format, ["foo~n", []]). result in “foo\n” output on the console of a@myhost? it is because the process that handles the rpc:call in b@myhost will have the group leader set to the group leader of the shell on a@myhost (the group leader of the process that executed rpc:call/3).

if you chain these rpc:call/3 thing through B to C, the same thing happens: the process that is group leader of the shell on a@myhost will be group leader of the rpc:call handling process on b@myhosy, and will be group leader of the rpc:call handling process on c@myhost. now since C can not reach A the io:format/2fails.

4 Likes

Thank you!!

… also node() will have been evaluated on A.

2 Likes