Elixir: escript: wrong path for NIF libraries

Created on 13 Nov 2016  路  2Comments  路  Source: elixir-lang/elixir

Environment

  • Elixir version (elixir -v):
Erlang/OTP 19 [erts-8.1] [source] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Elixir 1.3.4
  • Operating system:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 8.0 (jessie)
Release:    8.0
Codename:   jessie

To provide some context, this is a Raspeberry PI 3 with an external WiFi card. The program I'm working on uses :wierl and :epcap to put that WiFi card in monitor mode and read packets. The :epcap module includes a shared library which is built as deps/procket/priv/procket.so (btw, the built in WiFi card doesn't support monitor mode, that's why I'm using an external one.)

Current behavior

The project directory is sensor and mix escript.build builds the app as sensor.
It worked until I added the dependency from :epcap.

Then

$ ./sensor wlan1
11:22:03.317 [warn]  The on_load function for module procket returned {:error,
 {:load_failed,
  'Failed to load NIF library: \'/home/me/sensor/sensor/../priv/procket.so: cannot open
shared object file: Not a directory\''}}

** (UndefinedFunctionError) function :procket.socket/3 is undefined (module :procket
is not available)
    :procket.socket(:inet, :dgram, 0)
    src/wierl_config.erl:175: :wierl_config.down/1
    (sensor) lib/antenna.ex:4: Antenna.enter_monitor_mode/1
    (sensor) lib/sensor.ex:13: Sensor.start/1
    (elixir) lib/kernel/cli.ex:76: anonymous fn/3 in Kernel.CLI.exec_fun/2

Note that the path /home/me/sensor/sensor/../priv/procket.so is obviously wrong because of two reasons:

1) The second occurrence of sensor is actually a file (the app) and not a directory, and the path is wrong even if I manually create a priv dir under /home/me/sensor

2) The shared library is in deps/procket/priv/procket.so

There is another shared library in deps/epcap/priv/epcap_drv.so but it probably failed first on loading procket.so.

Running the application as a mix task or from iex -S mix works.

Expected behavior

Escript should load the shared library from its path /home/me/sensor/deps/procket/priv/procket.so

Unresolved

All 2 comments

Unfortunately that's a limitation of escripts. They cannot access anything in priv and therefore they cannot access embedded .so files. In other words, it is not currently possible to build escripts with NIFs in them.

For me, it works if I copy the NIFs into the path that my command line app built with mix escript.build states in its error message. In my case, I'm using fast_xml which comes with two NIFs, fxml.so and fxml_stream.so.

Without any further action by me, using my app results in

[error] failed to load NIF /Users/...../priv/lib/fxml_stream: Failed to load NIF library: 'dlopen(/Users/......./priv/lib/fxml_stream.so, 2): image not found'

Copying the libs into /priv/lib, the app works as expected. It's a little crude for a production environment, but can probably be automatized with a shell script.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michalmuskala picture michalmuskala  路  35Comments

josevalim picture josevalim  路  42Comments

josevalim picture josevalim  路  44Comments

josevalim picture josevalim  路  31Comments

p-adams picture p-adams  路  36Comments