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

Fallback with warning when the NIF cannot be loaded #157

Open
zacky1972 opened this issue Dec 12, 2020 · 4 comments
Open

Fallback with warning when the NIF cannot be loaded #157

zacky1972 opened this issue Dec 12, 2020 · 4 comments
Labels
enhancement New feature or request

Comments

@zacky1972
Copy link
Collaborator

Current Pelemay will fail to execute user code in defpelemay when the NIF generated by Pelemay cannot be loaded for some reasons.

So, Pelemay is expected to add a fallback feature to execute the user code by Elixir instead of native code in that case.

@zacky1972 zacky1972 added the enhancement New feature or request label Dec 12, 2020
@zacky1972
Copy link
Collaborator Author

I believe that will be useful to support mix upload.hotswap.

@zacky1972
Copy link
Collaborator Author

In case that NIFs exist but mix upload.hotswap is newer than them, Pelemay should give up to load NIFs and fallback to execute the user code by Elixir.

@zacky1972
Copy link
Collaborator Author

This issue is related to #156

@zacky1972
Copy link
Collaborator Author

zacky1972 commented Dec 13, 2020

Sorry, in Japanese.(I explained at Nerves JP Slack)

Pelemayの仕組みを説明すると,次のような感じです。

  1. defpelemay do … end の区間のASTをPelemayマクロが受け取る
  2. 関数ごとに解析してCコードを Application.app_dir(:pelemay, "src")に生成する
  3. Makefileを Applicatoin.app_dir(:pelemay, "build") に生成してビルドする。生成したNIFライブラリは Application.app_dir(:pelemay, "priv")に生成される
  4. スタブElixirコードを Application.app_dir(:pelemay, "priv")に生成する。このコードをロードすると NIFライブラリが読み込まれる。
  5. 元の関数をスタブElixirコードを呼び出すように書き換える

mix firmware && mix upload は,lib配下にあるモジュールに加えて,Application.app_dir(*, "priv") もターゲットに転送します。
これに対し,mix upload.hotswaplib 配下にあるモジュールをホットスワップしますが, Application.app_dir(*, "priv") をターゲットに転送することはしません。

したがって,Pelemayを組み込んだプロジェクトを mix upload.hotswap すると,上記の5だけが見えて,Application.app_dir(:pelemay, "priv") に配置したはずのNIFライブラリとスタブElixirコードが見えないので,スタブElixirコードのモジュールが存在しないというエラーになります。

NIFライブラリを転送することができないのはどうしようもないのですが,スタブElixirコードについては,ファイルを配置してロードするというアプローチをやめて,マクロで実現すれば,現状のmix upload.hotswapの仕組みで実現できます。

あとは,スタブElixirコードがNIFライブラリが存在しない,もしくは古いことを検出した場合に,NIFライブラリを読み込んで実行することを諦めて,元のElixirコードをそのまま実行するようにすれば良いというわけです。

実運用を考えた時,

  1. チョコチョコ修正しては,mix upload.hotswapで動作確認をして,というのをある程度繰り返し,
  2. コミットする前に mix firmware && mix uploadして動作確認をしてファームイメージを更新する,

というような感じになると思います。

このような運用の時に,Pelemayは,1のときには Elixir での実行で動作し,2 のときにはネイティブコードで動作するという感じにできれば良いかなと思います。

いったん2をすると,Application.app_dir(:pelemay, "priv")にNIFが転送されるので,そのあとで1をすると,NIFをロードした時に古いNIFを読み込んでしまうと不一致になってしまうと思います。

そこで,バージョンに1対1対応した番号を,スタブElixirコードと Application.app_dir(:pelemay, "priv") に埋め込んでおき,スタブコードのロード時にこの番号が一致した場合はNIFをロードし,一致しなかったりロードに失敗したら元のElixirコードを実行する,というようにすれば良いかなと思いました。

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

No branches or pull requests

1 participant