2015-07-04 15 views
8

Zdalny węzeł znajduje się na innym komputerze.erlang: nie powiodło się (węzeł, zabawa): błąd badfun

I testu z lokalnego węzła:

$ 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 

Przekonani spawn(node,module,function,args) prace, ale spawn(node,fun) nie.

Wersja Erlang na zdalnym węźle to R15, a wersja na węźle lokalnym to R17. Czy to jest powód? Ponieważ format kodu jest inny? Nie jestem pewien, jak Erlang marnuje zabawny typ podczas przekazywania go do zdalnego węzła. W bajtode?

Pomoc, proszę!

Odpowiedz

9

Jako komunikat o błędzie, który otrzymałeś, funkcja anonimowa jest traktowana w tym kontekście tak, jakby została zdefiniowana w module erl_eval. Jeśli masz tę samą wersję erl_eval zarówno w węźle nadawczym, jak i w węźle odbiorczym, wszystko działa poprawnie, ponieważ w tym przypadku obie kopie erl_eval mają tę samą wersję i sumy kontrolne, więc węzeł odbiorczy może poprawnie ocenić anonimową funkcję przekazaną od węzeł wysyłający. Ale jeśli oba węzły mają różne moduły erl_eval, ocena anonimowej funkcji zakończy się niepowodzeniem.

Ciekawą rzeczą jest, aby spróbować zdefiniować anonimową funkcję w węźle R15, konwertować je do binarny poprzez term_to_binary/1, wysłać lub skopiuj wynikowy plik binarny nad węzła 17.x, przekonwertować go z powrotem do wyrażenia poprzez binary_to_term/1 , a następnie przekazać wynikowy termin jako anonimową funkcję do Twojego połączenia spawn. Po pierwsze, na węźle R15:

([email protected])1> F = fun() -> io:format("hello~n") end. 
([email protected])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,...>> 
([email protected])3> file:write_file("/tmp/fun", Bin). 
ok 

teraz czytać binarny do węzła 17.x oraz wykonać połączenie spawn z nim z powrotem na węźle R15:

([email protected])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,...>>} 
([email protected])2> F = binary_to_term(Bin). 
#Fun<erl_eval.20.82930912> 
([email protected])3> spawn([email protected], F). 
hello 
<7101.90.0> 

Jak widać — i powinieneś sam tego wypróbować — wywołanie spawn działa zgodnie z oczekiwaniami, ponieważ anonimowa funkcja została utworzona na węźle R15 i tam również jest oceniana. Węzeł 17x tylko go przepuszcza.

+0

Dlaczego jest ograniczony do tej samej wersji erl_eval? Dopóki zabawa jest kompatybilna z wersją docelową, tzn. Polecane funkcje i semantyka są kompatybilne, to powinna działać na docelowym Erlangu, który jest bardziej elastyczny, ponieważ można wymieniać dowolne zgodne kody między węzłami, oprócz gotowych modułów . – kingluo

+3

W jaki sposób proponujesz weryfikację kompatybilności funkcji i semantyki modułu, aby dowolne anonimowe zabawy związane z tym modułem mogły być poprawnie wykonywane w różnych węzłach? Rozwiązanie tego problemu jest generalnie niepraktyczne. Środowisko wykonawcze Erlang sprawdza zatem sumę kontrolną MD5 modułu w celu sprawdzenia kompatybilności. –

Powiązane problemy