Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reloading of nif modules #12

Open
tinglei8 opened this issue Jun 23, 2015 · 5 comments
Open

Reloading of nif modules #12

tinglei8 opened this issue Jun 23, 2015 · 5 comments

Comments

@tinglei8
Copy link
Contributor

After a nif module is reloaded, all the nif functions are overwritten by elixir placeholders.

defmodule test_nif do

  require Logger

  @on_load :init

  def init() do
    :erlang.load_nif("./priv/test_nif", 0)
    :ok
  end

  def test_a() do
    Logger.error "NIF library not loaded"
  end

end

After reloading test_a.beam, test_nif.test_a() will call the placeholder instead of nif functions.

One way I can think of to solve the glitch is to add an _on_reprise_reload() function to test_nif:

def _on_reprise_reload() do 
  init()
end

And have reprise call the function after reloading the module

But there might be better ways.

@wkhere
Copy link
Owner

wkhere commented Jun 27, 2015

Hi!

I never worked with NIFs. So what I say is a good practice which comes to mind when handling corner cases like this one - assuming that there might be more similar corner cases around :)

More elegant solution would be to call some configured function on a reloaded NIF module (if it's exported). Name of such function - like _on_reprise_reload would go to your app config.exs.

The question is: how to detect that a module contains NIFs?

Are you able to come up with a prototype PR?

cheers,

W.

@tinglei8
Copy link
Contributor Author

Hi, Thanks for your advice!

I've come up with a simple fix to support a "general reload hook", not made for NIFs. In that case people can do all the things in the hook function, I think it's more general and useful than targeting NIF use cases specifically.

Didn't come up with a unit test yet but I already use it in my project and it worked great.

For my previous example, now it can be fixed like this:

defmodule test_nif do

  require Logger

  @on_load :init

  def init() do
    :erlang.load_nif("./priv/test_nif", 0)
    :ok
  end

  def _reprise_on_reload() do 
    init()
  end

  def test_a() do
    Logger.error "NIF library not loaded"
  end

end

@tinglei8
Copy link
Contributor Author

Hi, turns out there is a built-in reload feature for erlang nifs.

Just implement the 'load', 'upgrade', 'unload' callbacks for ERL_NIF_INIT macro and erlang handles nif reload for you when the module is reloaded, there is no need to call load_nif() again in _reprise_on_reload()

That said, maybe there are other aspects people can use a _reprise_on_reload() callback on reprise. I kept reload mechanism in my project and worked fine.

@wkhere
Copy link
Owner

wkhere commented Oct 20, 2015

Hello!

I hope you don't mind this project evolving rather slowly.. :)

I think you're right that _reprise_on_reload() can be useful. I see no reason in blocking this going to master which then gets "hexified" with all good implications of it.

Still I'm tempted to have a simple regression test for this, as I said previously in the pull request comment. Do you have an idea or a skeleton of how such test for a callback might work?

cheers,

W.

@tinglei8
Copy link
Contributor Author

tinglei8 commented Nov 9, 2015

Hi,

Sorry for the late reply! I was busy with the day jobs.

I've written a simple test to test calling hooks, not a very comprehensive one but I think it's better than nothing.

cheers,
Lei

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants