[erlang-questions] When is code_change triggered?

Paul Mineiro <>
Thu Jun 26 18:43:36 CEST 2008

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:

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

In an artificial world, only extremists live naturally.

        -- Paul Graham

More information about the erlang-questions mailing list