Erlang Mailing Lists

Author Message

<  Erlang bugs mailing list  ~  module reload problem in erl

Zoltan.Toth at eth.ericss
Posted: Wed Jul 16, 2003 4:57 pm Reply with quote
Guest
Hi,

I've found a problem which happens on Solaris (e.g. version 5.2.3.1) and Linux
(e.g. 5.2.3.3) similarly, described below.
I attached my simple test program, which manages a sorted list.

Do you think this is a bug in the Erlang virtual machine ?

Thanks for any info,
Zoltan

---------------------------------------------------------------------
Problem: c:c(Module) for the 2nd time kills/loses the existing instance of the process in the erl
shell.
(The same problem exists if I recompile with erlc and load with l(Module).)

Erlang (BEAM) emulator version 5.2.3.1
Compiled on Fri Feb 7 08:42:17 2003

1> sl:start().
true
2> process_info(whereis(listStore)).
[{registered_name,listStore},
{current_function,{sl,listLoop,1}},
{initial_call,{sl,listLoop,1}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.21.0>},
{heap_size,233},
{stack_size,4},
{reductions,1},
{garbage_collection,[{fullsweep_after,65535}]}]
4> sl:getList().
getList from <0.29.0>
[]
5> sl:addElem({lali,1}).
insert of lali, 1
{insert,{lali,1}}
6> sl:getList().
getList from <0.29.0>
[{lali,1}]

%% Recompile for the 1st time:

7> c:c(sl).
{ok,sl}

%% Now the process is still alive (and holds the data):

8> process_info(whereis(listStore)).
[{registered_name,listStore},
{current_function,{sl,listLoop,1}},
{initial_call,{sl,listLoop,1}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.21.0>},
{heap_size,233},
{stack_size,4},
{reductions,60},
{garbage_collection,[{fullsweep_after,65535}]}]

%% Compile & load again:

9> c:c(sl).
{ok,sl}

%% But now the process has died:

10> process_info(whereis(listStore)).

=ERROR REPORT==== 16-Jul-2003::11:39:06 ===
Error in process <0.29.0> with exit value:
{badarg,[{erlang,process_info,[undefined]},{erl_eval,expr,3},{erl_eval,exprs,4},{shell,eval_loop,2}]}
** exited: {badarg,[{erlang,process_info,[undefined]},
{erl_eval,expr,3},
{erl_eval,exprs,4},
{shell,eval_loop,2}]} **



Post generated using Mail2Forum (http://m2f.sourceforge.net)
Erik.Stenman at epfl.ch
Posted: Wed Jul 16, 2003 8:41 pm Reply with quote
Guest
> Hi,
>
> I've found a problem which happens on Solaris (e.g. version
> 5.2.3.1) and Linux (e.g. 5.2.3.3) similarly, described below.
> I attached my simple test program, which manages a sorted list.
>
> Do you think this is a bug in the Erlang virtual machine ?

No this is the intended behavior.
When you compile the module in the shell a new version of
the module is loaded. The previous version of the module which
is used by the code in your server is marked as old.

The second time you compile a third version of your module
gets loaded, but the runtime system will not let you have
more than two versions of a module loaded at a time.
(This is to prevent you from running old code by
mistake.) In order to enforce this all processes who have
references to the old code will be killed.

To keep your process alive you will need to force it
to switch to new code (this is done by a fully qualified call).
Example:

...
listLoop(L) ->
receive
{insert, {Key,Value}} ->
...
code_update -> ?MODULE:listLoop(L)
end.

update() ->
listStore ! code_update,
ok.

...
Now you can migrate your server to new code by calling sl:update() after a
recompile.

A better practice for servers is to replace all recursive calls by fully
qualified calls:
listLoop(L) ->
receive
{insert, {Key,Value}} ->
io:format("insert of ~w, ~w~n", [Key,Value]),
?MODULE:listLoop(insert({Key,Value}, L));
{P, getList} ->
io:format("getList from ~w~n", [P]),
P ! L, ?MODULE:listLoop(L);
shutdown ->
io:format("Castle of arrrrgggh...~n", []),
unregister(listStore), exit(normal);
code_update -> ?MODULE:listLoop(L)
end.

A problem with both these solutions is that you might need to update
the data in the server when you have loaded new code.
You could do this as:
A better practice for servers is to replace all recursive calls by fully
qualified calls:
listLoop(L) ->
receive
{insert, {Key,Value}} ->
io:format("insert of ~w, ~w~n", [Key,Value]),
?MODULE:listLoop(insert({Key,Value}, L));
{P, getList} ->
io:format("getList from ~w~n", [P]),
P ! L, ?MODULE:listLoop(L);
shutdown ->
io:format("Castle of arrrrgggh...~n", []),
unregister(listStore), exit(normal);
code_update -> %% Call this to prepare for an update.
%% Wait for the new code to be loaded.
receive
update_done -> ?MODULE:listLoop(?MODULE:update_data(L))
end
end.


update_data(L) -> L.

pre_update() ->
listStore ! code_update,
ok.

after_update() ->
listStore ! update_done,
ok.
...

Now you can safely do:
> sl:pre_update(),c(sl),sl:after_update().


Or you can use OTPs more general behaviour for a server,
but that is a lesson for some other time...


/Erik
--------------------------------------
Eric Conspiracy Secret Laboratories
I'm Happi, you should be happy.
Praeterea censeo "0xCA" scribere Erlang posse.



Post generated using Mail2Forum (http://m2f.sourceforge.net)

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum