[erlang-bugs] nif reload
Sverker Eriksson
sverker.eriksson@REDACTED
Mon May 26 14:51:10 CEST 2014
On 05/26/2014 01:43 AM, Tony Rogvall wrote:
> Hi!
>
> I have something strange niff stuff going on, I think.
> (tested R17/R16)
>
> I have a very simple demo nif application (attached), one function (not really
> needed) and
> a nif that I want to be able to load/upgrade/unload. I have removed the reload
> callback,
> that according to documentation is deprecated.
>
> Following sequence can be seen, when I repeat the
> > l(niffy).
> from the erlang shell.
>
>
> Eshell V6.1 (abort with ^G)
> 1> niffy:hello().
> Loading: ./niffy/priv/niffy_drv
> c_src/niffy_nif.c:61: niffy_load: *priv_data=0x0 ptr=0x1e1820e8, ptr->n
> c_src/niffy_nif.c:51: niffy_hello: priv_data=0x1e1820e8
> world
> 2> niffy:hello().
> c_src/niffy_nif.c:51: niffy_hello: priv_data=0x1e1820e8
> world
> 3> l(niffy).
> Loading: ./niffy/priv/niffy_drv
> c_src/niffy_nif.c:72: niffy_upgrade: *priv_data=0x0 *old_priv_data=0x1e1820e8
> ptr->n=1
> {module,niffy}
> 4> niffy:hello().
> c_src/niffy_nif.c:51: niffy_hello: priv_data=0x1e1820e8
> world
> 5> l(niffy).
> c_src/niffy_nif.c:81: niffy_unload: priv_data=0x1e1820e8 ptr->n=2
> Loading: ./niffy/priv/niffy_drv
> c_src/niffy_nif.c:72: niffy_upgrade: *priv_data=0x0 *old_priv_data=0x1e1820e8
> ptr->n=504889344
> {module,niffy}
> 6>
> 6> l(niffy).
> c_src/niffy_nif.c:81: niffy_unload: priv_data=0x1e1820e8 ptr->n=504889345
> Loading: ./niffy/priv/niffy_drv
> c_src/niffy_nif.c:72: niffy_upgrade: *priv_data=0x0 *old_priv_data=0x1e1820e8
> ptr->n=504889344
> {module,niffy}
> 7> l(niffy).
> c_src/niffy_nif.c:81: niffy_unload: priv_data=0x1e1820e8 ptr->n=504889345
> Segmentation fault: 11
>
> I can see that the unload is called and I free the priv_data, then upgrade is
> called on that very same memory.
> But why?
>
Your niffy_upgrade-callback does
*priv_data = *old_priv_data;
which means your old and new module instances share the same data.
You then free that data when the old instance is unloaded which leaves
the new module with a dangling pointer.
Either copy the data in niffy_upgrade or use reference counting in
niffy_unload:
if (--ptr->n == 0) {
enif_free(ptr);
}
/Sverker, Erlang/OTP
More information about the erlang-bugs
mailing list