2017-02-23 3 views
1

Zuerst ein Disclaimer Ich lerne Erlang. Kein Experte hier. Während ich einige Beispiele mit ETS machte, stieß ich auf etwas, das ich nicht verstehe (selbst nach der Suche).Anderes Verhalten der ETS mit und ohne Shell

Ich habe einen Prozess, in dem ich eine öffentliche ETS schaffen mit

TableID = ets:new(tablename, [public])} 

ich dann TableID an andere Prozesse übergeben. Wenn ich das mache, bilden die Module die Shell, alles ist in Ordnung. Wenn ich genau dieselben Module mit erl -noshell -s ... oder sogar ohne die Option -noshell ausführe, schlägt es fehl. Ich bekomme immer Fehler: badarg, als ob die Tabelle nicht existiert. Die ID wird ordnungsgemäß übergeben, aber die Tabelle verhält sich tatsächlich wie privat!

Gibt es einen Unterschied zwischen dem Ausführen von Modulen interaktiv von der Shell oder ohne?

Dank


ich ein Beispiel für den Code bin Hinzufügen ich das Problem versuchen bin mit und debuggen. Da es ein Stück einer größeren Software ist (und es ist im Grunde bis auf die Knochen entkernt, um das Problem zu finden), könnte es schwierig zu verstehen sein.

-record(loop_state, { 
     commands 
     }). 

start() -> 
    LoopState = #loop_state{commands = ets:new(commands, [public])}, 
    tcpserver_otp_backend:start(?MODULE, 7000, {?MODULE, loop}, LoopState). 

loop(Socket, LoopState = #loop_state{commands = Commands}) -> 
    case gen_tcp:recv(Socket, 0) of 
     {ok, Data} -> 
      % the call below fails, no error generated, AND only in non interactive shell 
      A = newCommand(Commands, Data), 
      gen_tcp:send(Socket, A), 
      loop(Socket, LoopState); 
     {error, closed} -> 
      ok 
    end. 


newCommand(CommandTableId, Command) -> 
    case ets:lookup(CommandTableId,Command) of 
     [] -> 
      _A = ets:insert(CommandTableId, {Command, 1}), 
      <<1, "new", "1">>; % used for testing 
     _ -> 
      <<1, "old", "1">> % used for testing 
    end. 

Wenn ich die „säumiger Befehl“ ets entfernen: Nachschlagen funktioniert alles wieder wie int er interaktiv Shell.

+0

Konnten Sie den relevanten Code bekannt geben, um die Fehlersituation zu reproduzieren? –

+0

getan, ich habe versucht, es ein bisschen zu reinigen, nur den Teil, den ich benutze, um zu versuchen, zu verstehen, was ich falsch mache. – Francesco

Antwort

2

Das Problem scheint zu sein, dass Sie die ETS-Tabelle in Ihrer start() - Funktion erstellen. Eine ETS-Tabelle hat einen Eigentümer (standardmäßig den Erstellungsprozess), und wenn der Besitzer stirbt, wird die Tabelle gelöscht. Wenn Sie die start/0-Funktion über die Befehlszeile ausführen, indem Sie -s an erl übergeben, wird dieser Besitzerprozess ein interner Prozess im Erlang-Kernel sein, der Teil der Verarbeitung der Startsequenz ist. Unabhängig davon, ob Sie -noshell übergeben oder nicht, ist dieser Prozess wahrscheinlich vorübergehend und wird absterben, bevor die Nachschlagefunktion Zeit für die Ausführung hat, sodass die Tabelle nicht mehr existiert, wenn die Suche schließlich stattfindet.

Der richtige Ort zum Erstellen der ETS-Tabelle wäre in der init() - Callback-Funktion des gen_Servers, den Sie starten. Wenn es sich um eine öffentliche est-Tabelle handeln soll, auf die von mehreren Prozessen zugegriffen wird, möchten Sie möglicherweise einen separaten Serverprozess erstellen, dessen Aufgabe es ist, die Tabelle zu besitzen.

+0

Ich denke, das Problem ist richtig, die Lösung weniger unmittelbar. Wenn man bedenkt, dass dies nur ein Beispiel ist, kann ich einfach eine andere Datenstruktur verwenden oder die ETS in einen eigenen Prozess einbetten – Francesco

+0

Es gibt eine interessante kleine Arbeit [hier] (http://steve.vinoski.net/blog/2011/03/ 23/dont-lose-your-ets-tables /) über dieses Thema: "Verliere deine ETS-Tische nicht". – Pascal

Verwandte Themen