简体   繁体   English

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

[英]erlang: failed to spawn(node, fun): badfun error

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)
(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

You could see that spawn(node,module,function,args) works, but the spawn(node,fun) does not. 你可以看到spawn(node,module,function,args)有效,但是spawn(node,fun)却没有。

The Erlang version on the remote node is R15, while the version on the local node is R17. 远程节点上的Erlang版本是R15,而本地节点上的版本是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. 我不清楚Erlang如何在将它传递给远程节点时编组有趣的类型。 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. 正如您收到的错误消息所示,匿名函数在此上下文中基本上被视为在erl_eval模块中定义。 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. 如果在发送节点和接收节点上都有相同版本的erl_eval ,一切正常,因为在这种情况下, erl_eval两个副本都具有相同的版本和校验和,因此接收节点能够正确评估从中传递的匿名函数发送节点。 But if the two nodes have different erl_eval modules, evaluating the anonymous function will fail. 但是如果两个节点具有不同的erl_eval模块,则评估匿名函数将失败。

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. 一个有趣的事情是在R15节点上定义匿名函数,通过term_to_binary/1将其转换为二进制,将生成的二进制文件发送或复制到17.x节点,通过binary_to_term/1将其转换回一个术语,然后将生成的术语作为匿名函数传递给您的spawn调用。 First, on the R15 node: 首先,在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

Now read the binary into the 17.x node, and make the spawn call with it back over to the R15 node: 现在将二进制文件读入17.x节点,并使用它返回到R15节点进行spawn调用:

(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. 正如您所看到的 - 您也应该自己尝试 - spawn调用按预期工作,因为匿名函数是在R15节点上创建的,并且它也在那里进行评估。 The 17.x node merely passes it through. 17.x节点只是通过它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM