The remote node is located in the different machine.
I test from the local node:
$ erl -name foobar
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false]
Eshell V6.2 (abort with ^G)
([email protected])1> Aliyun='[email protected]'.
'[email protected]'
([email protected])2> spawn(Aliyun, fun() -> io:format("hello~n") end).
<6108.86.0>
([email protected])3>
=ERROR REPORT==== 4-Jul-2015::21:03:27 ===
Error in process <0.86.0> on node '[email protected]' with exit value: {{badfun,#Fun<erl_eval.20.90072148>},[{erlang,apply,2,[]}]}
([email protected])3> spawn(Aliyun, io, format, ["hello~n"]).
hello
<6108.87.0>
([email protected])4> net_adm:ping(Aliyun).
pong
You could see that spawn(node,module,function,args)
works, but the spawn(node,fun)
does not.
The Erlang version on the remote node is R15, while the version on the local node is R17. Is it the reason? Because the code format is different? I'm not clear how Erlang marshal the fun type when passing it to the remote node. In bytecode?
Help please!
As the error message you received shows, the anonymous function is essentially treated in this context as if it were defined in the erl_eval
module. If you have the same version of erl_eval
on both the sending node and receiving node, everything works fine, since in that case both copies of erl_eval
have the same version and checksums, so the receiving node is correctly able to evaluate an anonymous function passed from the sending node. But if the two nodes have different erl_eval
modules, evaluating the anonymous function will fail.
An interesting thing to try is to define the anonymous function on the R15 node, convert it to a binary via term_to_binary/1
, send or copy the resulting binary over to the 17.x node, convert it back to a term via binary_to_term/1
, and then pass the resulting term as the anonymous function to your spawn
call. First, on the R15 node:
(r15@myhost)1> F = fun() -> io:format("hello~n") end.
(r15@myhost)2> Bin = term_to_binary(F).
<<131,112,0,0,2,179,0,158,45,156,12,16,101,74,154,214,21,
222,196,219,108,205,131,0,0,0,20,0,0,...>>
(r15@myhost)3> file:write_file("/tmp/fun", Bin).
ok
Now read the binary into the 17.x node, and make the spawn
call with it back over to the R15 node:
(r17@myhost)1> {ok, Bin} = file:read_file("/tmp/fun").
{ok,<<131,112,0,0,2,179,0,158,45,156,12,16,101,74,154,
214,21,222,196,219,108,205,131,0,0,0,20,...>>}
(r17@myhost)2> F = binary_to_term(Bin).
#Fun<erl_eval.20.82930912>
(r17@myhost)3> spawn(r15@myhost, F).
hello
<7101.90.0>
As you can see — and you should try it for yourself too — the spawn
call works as expected because the anonymous function was created on the R15 node and it's also being evaluated there. The 17.x node merely passes it through.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With