module reload problem in erl

Erik Stenman <>
Wed Jul 16 22:41:01 CEST 2003


> 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.




More information about the erlang-bugs mailing list