Hi all,<div><br></div><div>I've encountered a situation that makes my brain hurt and I was wondering if anyone could help me understand it. It's so strange that it may be a bug, if so please let me know and I'll do whatever groundwork is necessary to get it tracked down. Anyway on to the situation:</div>
<div><br></div><div>It appears that when:</div><div>* Executing a Fun,</div><div>* that contains a local function call,</div><div>* in a process running in the old code of a module that has both current and old versions loaded,</div>
<div>* the local function call will sometimes go to the current code and sometimes go to the old code.</div><div><br></div><div>It appears that the decision is based somehow on the content of the code in the current version.</div>
<div><br></div><div>Obviously an example is in order:</div><div><br></div><div>--- begin foo.erl ---</div><div><div>-module(foo).</div><div>-ifdef(BODY).</div><div>-export([start/0, loop/0]).</div><div>start() -></div>
<div>        register(?MODULE, spawn(?MODULE, loop, [])).</div><div>loop() -></div><div>        io:fwrite("loop version ~p\n", [?V]),</div><div>        receive</div><div>                _ -></div><div>                        F = fun () -> loop() end,</div>
<div>                        F()</div><div>        end.</div><div>-endif.</div></div><div>--- end foo.erl ---</div><div><br></div><div>Armed with this file, we can do this:</div><div><br></div><div><div>$ erl</div><div>Erlang R14B02 (erts-5.8.3) [source] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]</div>
<div><br></div><div>Eshell V5.8.3  (abort with ^G)</div><div>1> compile:file("foo", [{d,'BODY'}, {d,'V',1}]).</div><div>{ok,foo,[]}</div><div>2> foo:start().</div><div>loop version 1</div><div>
true</div><div>3> compile:file("foo", [{d,'BODY'}, {d,'V',2}]).</div><div>{ok,foo,[]}</div><div>4> code:load_file(foo).</div><div>{module,foo}</div><div>5> foo ! x.</div><div>loop version 2</div>
<div>x</div></div><div><br></div><div>The local function call in the Fun has called from the old version into the current version of the module (not what I expected).</div><div>Run the same sequence again but this time load a module that is empty:</div>
<div><br></div><div><div>$ erl</div><div>Erlang R14B02 (erts-5.8.3) [source] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]</div><div><br></div><div>Eshell V5.8.3  (abort with ^G)</div><div>1> compile:file("foo", [{d,'BODY'}, {d,'V',1}]).</div>
<div>{ok,foo,[]}</div><div>2> foo:start().</div><div>loop version 1</div><div>true</div><div>3> compile:file("foo", [{d,'V',2}]).</div><div>{ok,foo,[]}</div><div>4> code:load_file(foo).</div><div>
{module,foo}</div><div>5> foo ! x.</div><div>loop version 1</div><div>x</div></div><div><br></div><div>The local function call in the Fun has stayed in the old version of the module (actually what I expected).</div><div>
<br></div><div>Some changes other than emptying the body of the module seem to have a similar effect but I haven't tracked down exactly what the trigger is.</div><div><br></div><div>My system is Ubuntu 11.04 running Erlang R14B02 and I haven't yet checked older versions of Erlang for the same behaviour.</div>
<div><br></div><div>Thanks,</div><div>Sam.</div>