[erlang-questions] When is code_change triggered?

Geoff Cant <>
Fri Jun 27 10:32:59 CEST 2008

Hi all, I puzzled about this one for a while too before stumbling onto
the 'sys' module.

gen_(server|fsm|event) code_change/3 callbacks are invoked by a
corresponding call to sys:change_code/4. The small caveat being that the
process in question must be suspended (it goes into a loop where it only
processes other 'sys' messages).

So to do code upgrade of the only gen_server in a system (Pid) running
the callback module (Mod), you want something like:

Upgrade = fun (Pid, Mod) -> c:l(Mod),
                            sys:change_code(Pid, Mod, foo, foo),

Extending that to all the Pids running a callback mod is pretty easy
too. The 'foo' dummy arguments are the version number we're upgrading
from and the extra information we need for the upgrade.

Hope this helps,

Paul Mineiro <> writes:

> We had the same at question here in Hazzard County several months ago.
> Hot code loading is a low-level feature built into the runtime; there's
> space for two versions of a module and using module-prefixed calls implies
> a call into the latest version (and a local call implies continue to use
> the same module version).  Before you hot code load a module, you have to
> first nuke the oldest version of the module (and any lingering processes).
> This is the purpose of code:purge/1 and code:soft_purge/1.  You can then
> load a new module using code:load_file/1, code:load_abs/1,
> code:load_binary/3, etc.  After loading the formerly newest version of the
> code will now occupy the oldest version slot.
> Code change is a high-level feature which is implemented by convention in
> the OTP libraries.  The gen_X family has an inner loop which responds to
> special "system messages" which cause the process to transfer control to a
> seperate receive loop which only processes special upgrade messages, which
> ultimately cause the code_change/3 callback to be called.  In this manner
> you will not process further normal gen_X messages until the new code has
> been loaded and the code_change handler called.  This sequence is
> orchestrated by release_handler via calls like
> release_handler:install_release/1 and release_handler:upgrade_app/2.
> The final piece of information is that calling c(Module) in the shell is
> shorthand for invoking the compiler and then invoking the various code
> methods for loading the new version of the module.  It is *not*, however,
> shorthand for invoking the release_handler; that wouldn't make sense
> for many reasons.  (The shortest path to seeing your code_change/3 handler
> called is, imho, rather long).
> Hope that helps,
> -- p
> p.z. after figuring this out we wrote erlrc:
> http://code.google.com/p/erlrc/
> On Thu, 26 Jun 2008, tsuraan wrote:
>> When I started playing with gen_server a few years ago, I recalled
>> that doing a c(module) in the REPL would immediately update the code
>> of my running servers.  Now, I cannot get that to happen, so I'm
>> trying to figure out what I'm doing wrong.  My test server is minimal:
>> -module(test).
>> -export([start_link/0, start/0]).
>> -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
>>          terminate/2, code_change/3]).
>> start_link() ->
>>   gen_server:start_link({ local, ?MODULE }, ?MODULE, [], []).
>> start() ->
>>   gen_server:start({ local, ?MODULE }, ?MODULE, [], []).
>> init([]) ->
>>   process_flag(trap_exit, true),
>>   { ok, {}}.
>> handle_call(Msg, From, State) ->
>>   io:format("Unexpected Call ~p From ~p~n", [Msg, From]),
>>   { reply, { error, badcall }, State }.
>> handle_cast(Msg, State) ->
>>   io:format("Unexpected Cast ~p~n", [Msg]),
>>   { noreply, State }.
>> handle_info(Msg, State) ->
>>   io:format("Unexpected Info ~p~n", [Msg]),
>>   { noreply, State }.
>> terminate(Reason, _State) ->
>>   io:format("Terminating ~p for reason ~p~n", [ self(), Reason ]),
>>   ok.
>> code_change(OldVsn, State, Extra) ->
>>   io:format("Upgrading from ~p with extra data ~p~n", [OldVsn, Extra]),
>>   { ok, State }.
>> I can run this with test:start(), but subsequent c(test) never print
>> the message "Upgrading from ...".  Can anyone tell what I'm doing
>> wrong, or is my memory just bad and c(module) has never caused running
>> instances of that module to be upgraded?
>> _______________________________________________
>> erlang-questions mailing list
>> http://www.erlang.org/mailman/listinfo/erlang-questions

More information about the erlang-questions mailing list