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(-)
(limited to 'erts/doc')
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