erlang:无法生成(节点,有趣):badfun错误

kin*_*luo 7 erlang

远程节点位于不同的计算机中.

我从本地节点测试:

$ 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)
(foobar@debian.localdomain)1> Aliyun='aliyun@localhost2.localdomain'.
'aliyun@localhost2.localdomain'
(foobar@debian.localdomain)2> spawn(Aliyun, fun() -> io:format("hello~n") end).
<6108.86.0>
(foobar@debian.localdomain)3> 
=ERROR REPORT==== 4-Jul-2015::21:03:27 ===
Error in process <0.86.0> on node 'aliyun@localhost2.localdomain' with exit value: {{badfun,#Fun<erl_eval.20.90072148>},[{erlang,apply,2,[]}]}


(foobar@debian.localdomain)3> spawn(Aliyun, io, format, ["hello~n"]).          
hello
<6108.87.0>
(foobar@debian.localdomain)4> net_adm:ping(Aliyun).
pong
Run Code Online (Sandbox Code Playgroud)

你可以看到它spawn(node,module,function,args)有效,但spawn(node,fun)事实并非如此.

远程节点上的Erlang版本是R15,而本地节点上的版本是R17.是原因吗?因为代码格式不同?我不清楚Erlang如何在将它传递给远程节点时编组有趣的类型.在字节码?

请帮忙!

Ste*_*ski 9

正如您收到的错误消息所示,匿名函数基本上在此上下文中被视为已在erl_eval模块中定义.如果erl_eval在发送节点和接收节点上都有相同的版本,一切正常,因为在这种情况下,两个副本erl_eval具有相同的版本和校验和,因此接收节点能够正确地评估从发送传递的匿名函数节点.但是如果两个节点具有不同的erl_eval模块,则评估匿名函数将失败.

尝试一个有趣的事情是在R15节点上定义匿名函数,将其转换为二进制,通过term_to_binary/1发送或复制生成的二进制文件到17.x节点,将其转换回一个术语binary_to_term/1,然后传递结果term作为您spawn呼叫的匿名功能.首先,在R15节点上:

(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
Run Code Online (Sandbox Code Playgroud)

现在将二进制文件读入17.x节点,然后将其spawn调用回R15节点:

(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>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的 - 您也应该自己尝试 - spawn调用按预期工作,因为匿名函数是在R15节点上创建的,并且它也在那里进行评估.17.x节点只是通过它.

  • 您如何建议验证模块的功能和语义的兼容性,以便可以跨不同节点正确执行与该模块关联的任意匿名funs?解决这个问题通常是不切实际的.因此,Erlang运行时检查模块的MD5校验和以验证兼容性. (3认同)