From 8a273f85e26ad7ae533b0d9e5f429be34ee8a537 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Tue, 6 Nov 2012 00:42:49 +0100 Subject: Add clearer warnings about misuse of NIF and driver functionality --- erts/doc/src/driver_entry.xml | 23 ++++++++++ erts/doc/src/erl_driver.xml | 57 ++++++++++++++++++++----- erts/doc/src/erl_nif.xml | 97 ++++++++++++++++++++++++++++++------------- 3 files changed, 138 insertions(+), 39 deletions(-) diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index a2efdf3ebc..929c485c36 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -34,6 +34,29 @@ driver_entry The driver-entry structure used by erlang drivers. + +

Use this functionality with extreme care!

+

A driver callback is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can not provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the driver callback function doesn't behave well, + the whole VM will misbehave.

+ +

A driver callback that crash will crash the whole VM.

+

An erroneously implemented driver callback might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the driver callback.

+

A driver callback that do + lengthy work + before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.

+
+

As of erts version 5.9 (OTP release R15B) the driver interface has been changed with larger types for the callbacks diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 187c263b60..e16fd744c0 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -34,6 +34,32 @@ erl_driver API functions for an Erlang driver +

An Erlang driver is a library containing a set of native driver + callback functions that the Erlang VM calls when certain + events occur. There may be multiple instances of a driver, each + instance is associated with an Erlang port.

+ +

Use this functionality with extreme care!

+

A driver callback is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can not provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the driver callback function doesn't behave well, + the whole VM will misbehave.

+ +

A driver callback that crash will crash the whole VM.

+

An erroneously implemented driver callback might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the driver callback.

+

A driver callback that do lengthy + work before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.

+
+

As of erts version 5.5.3 the driver interface has been extended (see extended marker). The extended interface introduce @@ -53,16 +79,12 @@

The driver calls back to the emulator, using the API functions declared in erl_driver.h. They are used for outputting data from the driver, using timers, etc.

-

A driver is a library with a set of function that the emulator - calls, in response to Erlang functions and message - sending. There may be multiple instances of a driver, each - instance is connected to an Erlang port. Every port has a port - owner process. Communication with the port is normally done - through the port owner process.

-

Most of the functions take the port handle as an - argument. This identifies the driver instance. Note that this - port handle must be stored by the driver, it is not given when - the driver is called from the emulator (see +

Each driver instance is associated with a port. Every port + has a port owner process. Communication with the port is normally + done through the port owner process. Most of the functions take + the port handle as an argument. This identifies the driver + instance. Note that this port handle must be stored by the driver, + it is not given when the driver is called from the emulator (see driver_entry).

Some of the functions take a parameter of type ErlDrvBinary, a driver binary. It should be both @@ -129,6 +151,21 @@ are only thread safe when used in a runtime system with SMP support.

+

+ As mentioned in the warning text at + the beginning of this document it is of vital importance that a driver callback + does return relatively fast. It is hard to give an exact maximum amount + of time that a driver callback is allowed to work, but as a rule of thumb + a well behaving driver callback should return before a millisecond has + passed. This can be achieved using different approaches. + If you have full control over the code that are to execute in the driver + callback, the best approach is to divide the work into multiple chunks of + work and trigger multiple calls to the + timeout callback using + zero timeouts. This might, however, not always be possible, e.g. when + calling third party libraries. In this case you typically want to dispatch + the work to another thread. Information about thread primitives can be + found below.

diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index f484e9eaf7..f00f7b9f46 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -34,30 +34,6 @@ erl_nif API functions for an Erlang NIF library -

The NIF concept is officially supported from R14B. NIF source code - written for earlier experimental versions might need adaption to run on R14B.

-

No incompatible changes between R14B and R14A.

-

Incompatible changes between R14A and R13B04:

- - Environment argument removed for enif_alloc, - enif_realloc, enif_free, enif_alloc_binary, - enif_realloc_binary, enif_release_binary, - enif_alloc_resource, enif_release_resource, - enif_is_identical and enif_compare. - Character encoding argument added to enif_get_atom - and enif_make_existing_atom. - Module argument added to enif_open_resource_type - while changing name spaces of resource types from global to module local. - -

Incompatible changes between R13B04 and R13B03:

- - The function prototypes of the NIFs have changed to expect argc and argv - arguments. The arity of a NIF is by that no longer limited to 3. - enif_get_data renamed as enif_priv_data. - enif_make_string got a third argument for character encoding. - -
-

A NIF library contains native implementation of some functions of an Erlang module. The native implemented functions (NIFs) are called like any other functions without any difference to the @@ -67,6 +43,57 @@ is to throw an exception. But it can also be used as a fallback implementation if the NIF library is not implemented for some architecture.

+ +

Use this functionality with extreme care!

+

A native function is executed as a direct extension of the + native code of the VM. Execution is not made in a safe environment. + The VM can not provide the same services as provided when + executing Erlang code, such as preemptive scheduling or memory + protection. If the native function doesn't behave well, the whole + VM will misbehave.

+ +

A native function that crash will crash the whole VM.

+

An erroneously implemented native function might cause + a VM internal state inconsistency which may cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the call + to the native function.

+

A native function that do lengthy + work before returning will degrade responsiveness of the VM, + and may cause miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad load + balancing between schedulers. Strange behaviors that might occur due + to lengthy work may also vary between OTP releases.

+
+
+ +

The NIF concept is officially supported from R14B. NIF source code + written for earlier experimental versions might need adaption to run on R14B + or later versions:

+ + No incompatible changes between R14B and R14A. + Incompatible changes between R14A and R13B04: + + Environment argument removed for enif_alloc, + enif_realloc, enif_free, enif_alloc_binary, + enif_realloc_binary, enif_release_binary, + enif_alloc_resource, enif_release_resource, + enif_is_identical and enif_compare. + Character encoding argument added to enif_get_atom + and enif_make_existing_atom. + Module argument added to enif_open_resource_type + while changing name spaces of resource types from global to module local. + + + Incompatible changes between R13B04 and R13B03: + + The function prototypes of the NIFs have changed to expect argc and argv + arguments. The arity of a NIF is by that no longer limited to 3. + enif_get_data renamed as enif_priv_data. + enif_make_string got a third argument for character encoding. + + + +

A minimal example of a NIF library can look like this:

@@ -136,7 +163,23 @@ ok then retrieved by calling enif_priv_data.

There is no way to explicitly unload a NIF library. A library will be automatically unloaded when the module code that it belongs to is purged - by the code server.

+ by the code server.

+ +

+ As mentioned in the warning text at + the beginning of this document it is of vital importance that a native function + does return relatively fast. It is hard to give an exact maximum amount + of time that a native function is allowed to work, but as a rule of thumb + a well behaving native function should return to its caller before a + millisecond has passed. This can be achieved using different approaches. + If you have full control over the code that are to execute in the native + function, the best approach is to divide the work into multiple chunks of + work and call the native function multiple times. This might, however, + not always be possible, e.g. when calling third party libraries. In this + case you typically want to dispatch the work to another thread, return + from the native function, and wait for the result. The thread can send + the result back to the calling thread using message passing. Information + about thread primitives can be found below.

FUNCTIONALITY @@ -266,10 +309,6 @@ ok mutable.

The library initialization callbacks load, reload and upgrade are all thread-safe even for shared state data.

-

Avoid doing lengthy work in NIF calls as that may degrade the - responsiveness of the VM. NIFs are called directly by the same scheduler - thread that executed the calling Erlang code. The calling scheduler will thus - be blocked from doing any other work until the NIF returns.

-- cgit v1.2.3