7

I have a nif library and every time i recompile it, I must restart the shell to reload or upgrade this library.

Here is my erlang code:

-module(q4).
-export([init/0]).

-on_load(init/0).


init() ->
    erlang:load_nif("./q4_nif", reload).

Every time i compile the erlang module, this error occurs:

`The on_load function for module q4 returned {error,
                                         {upgrade,
                                          "Upgrade not supported by this NIF library."}}`

and when i call init/0 function, this error occurs: {error,{reload,"Reload not supported by this NIF library."}}

Is there anyway to fix this problem and load new nif library without restarting the shell?

Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73
Amin
  • 755
  • 6
  • 21

2 Answers2

6

As the error message indicates, you need to provide an upgrade function in your NIF, which you specify in your call to ERL_NIF_INIT:

ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)

The upgrade function is documented in the erl_nif man page.

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
  • I filled this arguments and above errors fixed but still erlang vm not loads new nif version and uses the older version. – Amin Oct 30 '15 at 08:59
  • 1
    In an Erlang 17 or 18 shell, when I reload an Erlang module, call it `foo` for example, that uses `on_load` to load a NIF, the upgrade function in the NIF runs. Type `l(foo). or `c(foo).` in the shell and the upgrade function is invoked and everything reloads properly, which is exactly what should happen. If you're seeing "reload not supported" errors, this means you're calling a function in your already-loaded Erlang module that is then trying to reload your NIF, and you shouldn't do that. Make sure your NIF has an upgrade function, and use `l(your_module).` to reload both the module and NIF. – Steve Vinoski Oct 30 '15 at 12:11
2

UPDATE Root cause found

It appears delete must called twice before hot-reloading NIFs. This seems like a erlang bug.

force_upgrade_module(Mod) ->
  true == code:purge(Mod),
  true == code:delete(Mod),
  code:purge(Mod),
  code:delete(Mod),
  {module,Mod} == code:load(Mod).

Even with implementing upgrade in ERL_NIF_INIT, there are still some issues that may or may not be platform-specific. For example, on macOS: feel free to delete the priv/{{module}}.so after calling load_nif in the erlang stub module and it will just continue silently succeed and not really reload the NIF .so.