Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
erl_ddll(3)		   Erlang Module Definition		   erl_ddll(3)

NAME
       erl_ddll	- Dynamic driver loader	and linker.

DESCRIPTION
       This  module  provides  an  interface  for loading and unloading	Erlang
       linked-in drivers in runtime.

   Note:
       This is a large reference document. For casual use of this module,  and
       for  most real world applications, the descriptions of functions	load/2
       and unload/1 are	enough to getting started.

       The driver is to	be provided as a dynamically linked library in an  ob-
       ject  code  format specific for the platform in use, that is, .so files
       on most Unix systems and	.ddl files on  Windows.	 An  Erlang  linked-in
       driver must provide specific interfaces to the emulator,	so this	module
       is not designed for loading arbitrary dynamic libraries.	For  more  in-
       formation about Erlang drivers, see erts:erl_driver .

       When describing a set of	functions (that	is, a module, a	part of	a mod-
       ule, or an application),	executing in a process and wanting  to	use  a
       ddll-driver,  we	use the	term user. A process can have many users (dif-
       ferent modules needing the same driver) and many	processes running  the
       same code, making up many users of a driver.

       In  the	basic  scenario, each user loads the driver before starting to
       use it and unloads the driver when done.	The reference  counting	 keeps
       track  of  processes  and the number of loads by	each process. This way
       the driver is only unloaded when	no one wants it	(it has	no user).  The
       driver  also  keeps  track of ports that	are opened to it. This enables
       delay of	unloading until	all ports are closed, or killing of all	 ports
       that use	the driver when	it is unloaded.

       The  interface  supports	 two basic scenarios of	loading	and unloading.
       Each scenario can also have the option of either	killing	ports when the
       driver  is unloading, or	waiting	for the	ports to close themselves. The
       scenarios are as	follows:

	 Load and Unload on a "When Needed Basis":
	   This	(most common) scenario simply supports that each user  of  the
	   driver  loads  it when needed and unloads it	when no	longer needed.
	   The driver is always	reference counted and as  long	as  a  process
	   keeping  the	driver loaded is still alive, the driver is present in
	   the system.

	   Each	user of	the driver use literally the  same  pathname  for  the
	   driver when demanding load, but the users are not concerned with if
	   the driver is already loaded	from the file system or	if the	object
	   code	must be	loaded from file system.

	   The following two pairs of functions	support	this scenario:

	   load/2 and unload/1:
	     When using	the load/unload	interfaces, the	driver is not unloaded
	     until the last port using the driver is closed. Function unload/1
	     can  return  immediately,	as the users have no interrest in when
	     the unloading occurs. The driver is unloaded when no one needs it
	     any longer.

	     If	 a  process having the driver loaded dies, it has the same ef-
	     fect as if	unloading is done.

	     When loading, function load/2 returns ok when any instance	of the
	     driver  is	 present. Thus,	if a driver is waiting to get unloaded
	     (because of open ports), it simply	changes	 state	to  no	longer
	     need unloading.

	   load_driver/2 and unload_driver/1:
	     These interfaces are intended to be used when it is considered an
	     error that	ports are open to a driver that	no  user  has  loaded.
	     The  ports	 that  are  still  open	 when  the last	user calls un-
	     load_driver/1 or when the last process having the	driver	loaded
	     dies, are killed with reason driver_unloaded.

	     The  function  names  load_driver	and unload_driver are kept for
	     backward compatibility.

	 Loading and Reloading for Code	Replacement:
	   This	scenario can occur if the driver code needs replacement	during
	   operation of	the Erlang emulator. Implementing driver code replace-
	   ment	is a little more tedious than Beam code	 replacement,  as  one
	   driver  cannot be loaded as both "old" and "new" code. All users of
	   a driver must have it closed	(no open ports)	before	the  old  code
	   can be unloaded and the new code can	be loaded.

	   The unloading/loading is done as one	atomic operation, blocking all
	   processes in	the system from	using the driver in question while  in
	   progress.

	   The	preferred way to do driver code	replacement is to let one sin-
	   gle process keep track of the driver. When the process starts,  the
	   driver  is  loaded.	When  replacement  is  required, the driver is
	   reloaded. Unload is probably	never done, or done when  the  process
	   exits. If more than one user	has a driver loaded when code replace-
	   ment	is demanded, the  replacement  cannot  occur  until  the  last
	   "other" user	has unloaded the driver.

	   Demanding  reload when a reload is already in progress is always an
	   error. Using	the high-level functions, it is	also an	error  to  de-
	   mand	reloading when more than one user has the driver loaded.

	   To simplify driver replacement, avoid designing your	system so that
	   more	than one user has the driver loaded.

	   The two functions for reloading drivers are	to  be	used  together
	   with	 corresponding load functions to support the two different be-
	   haviors concerning open ports:

	   load/2 and reload/2:
	     This pair of functions is used when reloading is to be done after
	     the last open port	to the driver is closed.

	     As	 reload/2  waits  for  the  reloading  to occur, a misbehaving
	     process keeping open ports	to the driver (or keeping  the	driver
	     loaded)  can cause	infinite waiting for reload. Time-outs must be
	     provided outside of the process demanding the reload or by	 using
	     the  low-level  interface	try_load/3  in combination with	driver
	     monitors.

	   load_driver/2 and reload_driver/2:
	     This pair of functions are	used when open ports to	the driver are
	     to	 be killed with	reason driver_unloaded to allow	for new	driver
	     code to get loaded.

	     However, if  another  process  has	 the  driver  loaded,  calling
	     reload_driver  returns error code pending_process.	As stated ear-
	     lier, the recommended design is to	not allow other	users than the
	     "driver reloader" to demand loading of the	driver in question.

DATA TYPES
       driver()	= iolist() | atom()

       path() =	string() | atom()

EXPORTS
       demonitor(MonitorRef) ->	ok

	      Types:

		 MonitorRef = reference()

	      Removes  a driver	monitor	in much	the same way as	erlang:demoni-
	      tor/1 in ERTS does with process monitors.	For details about  how
	      to  create  driver  monitors,  see  monitor/2,  try_load/3,  and
	      try_unload/2.

	      The function throws a badarg exception if	the parameter is not a
	      reference().

       format_error(ErrorDesc) -> string()

	      Types:

		 ErrorDesc = term()

	      Takes an ErrorDesc returned by load, unload, or reload functions
	      and returns a string that	describes the error or warning.

	  Note:
	      Because of peculiarities in the dynamic  loading	interfaces  on
	      different	 platforms,  the returned string is only guaranteed to
	      describe the correct error if format_error/1 is  called  in  the
	      same  instance  of  the  Erlang virtual machine as the error ap-
	      peared in	(meaning the same operating system process).

       info() -> AllInfoList

	      Types:

		 AllInfoList = [DriverInfo]
		 DriverInfo = {DriverName, InfoList}
		 DriverName = string()
		 InfoList = [InfoItem]
		 InfoItem = {Tag :: atom(), Value :: term()}

	      Returns a	list of	tuples {DriverName, InfoList}, where  InfoList
	      is the result of calling info/1 for that DriverName. Only	dynam-
	      ically linked-in drivers are included in the list.

       info(Name) -> InfoList

	      Types:

		 Name =	driver()
		 InfoList = [InfoItem, ...]
		 InfoItem = {Tag :: atom(), Value :: term()}

	      Returns a	list of	tuples {Tag, Value}, where Tag is the informa-
	      tion  item  and  Value is	the result of calling info/2 with this
	      driver name and this tag.	The result is a	tuple list  containing
	      all information available	about a	driver.

	      The following tags appears in the	list:

		* processes

		* driver_options

		* port_count

		* linked_in_driver

		* permanent

		* awaiting_load

		* awaiting_unload

	      For a detailed description of each value,	see info/2.

	      The  function  throws  a	badarg	exception if the driver	is not
	      present in the system.

       info(Name, Tag) -> Value

	      Types:

		 Name =	driver()
		 Tag =
		     processes |
		     driver_options |
		     port_count	|
		     linked_in_driver |
		     permanent |
		     awaiting_load |
		     awaiting_unload
		 Value = term()

	      Returns specific information about one aspect of a  driver.  Pa-
	      rameter Tag specifies which aspect to get	information about. The
	      return Value differs between different tags:

		processes:
		  Returns all processes	containing users of the	specific driv-
		  ers  as a list of tuples {pid(),integer() _= 0}, where inte-
		  ger()	denotes	the number of users in process pid().

		driver_options:
		  Returns a list of the	driver options provided	when  loading,
		  and any options set by the driver during initialization. The
		  only valid option is kill_ports.

		port_count:
		  Returns the number of	ports (an integer() _=	0)  using  the
		  driver.

		linked_in_driver:
		  Returns a boolean(), which is	true if	the driver is a	stati-
		  cally	linked-in one, otherwise false.

		permanent:
		  Returns a boolean(), which is	true if	the  driver  has  made
		  itself permanent (and	is not a statically linked-in driver),
		  otherwise false.

		awaiting_load:
		  Returns a list of all	processes having monitors for  loading
		  active.  Each	process	is returned as {pid(),integer()	_= 0},
		  where	integer() is the number	of monitors  held  by  process
		  pid().

		awaiting_unload:
		  Returns  a list of all processes having monitors for unload-
		  ing active. Each process is returned as {pid(),integer()  _=
		  0},  where  integer()	 is  the  number  of  monitors held by
		  process pid().

	      If option	linked_in_driver or permanent returns true, all	 other
	      options return linked_in_driver or permanent, respectively.

	      The  function  throws  a	badarg	exception if the driver	is not
	      present in the system or if the tag is not supported.

       load(Path, Name)	-> ok |	{error,	ErrorDesc}

	      Types:

		 Path =	path()
		 Name =	driver()
		 ErrorDesc = term()

	      Loads and	links the dynamic driver Name. Path is a file path  to
	      the directory containing the driver. Name	must be	a sharable ob-
	      ject/dynamic library. Two	drivers	with different Path parameters
	      cannot  be  loaded under the same	name. Name is a	string or atom
	      containing at least one character.

	      The Name specified is to correspond to the filename of  the  dy-
	      namically	 loadable object file residing in the directory	speci-
	      fied as Path, but	without	the  extension	(that  is,  .so).  The
	      driver  name  provided in	the driver initialization routine must
	      correspond with the filename, in much the	 same  way  as	Erlang
	      module names correspond to the names of the .beam	files.

	      If  the driver was previously unloaded, but is still present be-
	      cause of open ports to it, a call	to load/2 stops	the  unloading
	      and  keeps  the  driver (as long as Path is the same), and ok is
	      returned.	If you really want the object code to be reloaded, use
	      reload/2 or the low-level	interface try_load/3 instead. See also
	      the description of different scenarios for loading/unloading  in
	      the introduction.

	      If  more than one	process	tries to load an already loaded	driver
	      with the same Path, or if	the same process tries to load it many
	      times,  the function returns ok. The emulator keeps track	of the
	      load/2 calls, so that a corresponding number of  unload/2	 calls
	      must  be	done  from the same process before the driver gets un-
	      loaded. It is therefore safe for an application to load a	driver
	      that is shared between processes or applications when needed. It
	      can safely be unloaded without causing trouble for  other	 parts
	      of the system.

	      It  is  not  allowed to load multiple drivers with the same name
	      but with different Path parameters.

	  Note:
	      Path is interpreted literally, so	that all loaders of  the  same
	      driver  must specify the same literal Path string, although dif-
	      ferent paths can point out the same directory in the file	system
	      (because of use of relative paths	and links).

	      On  success,  the	 function  returns  ok.	On failure, the	return
	      value is {error,ErrorDesc}, where	ErrorDesc is an	opaque term to
	      be  translated  into  human readable form	by function format_er-
	      ror/1.

	      For more control over the	error handling,	use the	try_load/3 in-
	      terface instead.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       load_driver(Path, Name) -> ok | {error, ErrorDesc}

	      Types:

		 Path =	path()
		 Name =	driver()
		 ErrorDesc = term()

	      Works essentially	as load/2, but loads the driver	with other op-
	      tions.  All  ports  using	 the  driver  are  killed  with	reason
	      driver_unloaded when the driver is to be unloaded.

	      The number of loads and unloads by  different  users  influences
	      the  loading  and	 unloading  of a driver	file. The port killing
	      therefore	only occurs when the last user unloads the driver,  or
	      when the last process having loaded the driver exits.

	      This  interface  (or at least the	name of	the functions) is kept
	      for backward compatibility. Using	 try_load/3  with  {driver_op-
	      tions,[kill_ports]} in the option	list gives the same effect re-
	      garding the port killing.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       loaded_drivers()	-> {ok,	Drivers}

	      Types:

		 Drivers = [Driver]
		 Driver	= string()

	      Returns  a  list of all the available drivers, both (statically)
	      linked-in	and dynamically	loaded ones.

	      The driver names are returned as a list of strings rather	than a
	      list of atoms for	historical reasons.

	      For more information about drivers, see info.

       monitor(Tag, Item) -> MonitorRef

	      Types:

		 Tag = driver
		 Item =	{Name, When}
		 Name =	driver()
		 When =	loaded | unloaded | unloaded_only
		 MonitorRef = reference()

	      Creates  a driver	monitor	and works in many ways as erlang:moni-
	      tor/2 in ERTS, does for processes. When a	driver changes	state,
	      the  monitor  results  in	 a monitor message that	is sent	to the
	      calling process. MonitorRef returned by  this  function  is  in-
	      cluded in	the message sent.

	      As with process monitors,	each driver monitor set	only generates
	      one single message. The monitor is "destroyed" after the message
	      is sent, so it is	then not needed	to call	demonitor/1.

	      MonitorRef  can  also be used in subsequent calls	to demonitor/1
	      to remove	a monitor.

	      The function accepts the following parameters:

		Tag:
		  The monitor tag is always driver, as this function can  only
		  be  used  to	create	driver monitors. In the	future,	driver
		  monitors will	be integrated with process monitors, why  this
		  parameter has	to be specified	for consistence.

		Item:
		  Parameter Item specifies which driver	to monitor (the	driver
		  name)	and which state	change to monitor. The parameter is  a
		  tuple	 of  arity  two	whose first element is the driver name
		  and second element is	one of the following:

		  loaded:
		    Notifies when the driver is	reloaded (or loaded if loading
		    is	underway). It only makes sense to monitor drivers that
		    are	in the process of being	loaded or reloaded.  A	future
		    driver name	for loading cannot be monitored. That only re-
		    sults in a DOWN message sent immediately.  Monitoring  for
		    loading  is	 therefore most	useful when triggered by func-
		    tion try_load/3, where the monitor is created because  the
		    driver is in such a	pending	state.

		    Setting  a	driver monitor for loading eventually leads to
		    one	of the following messages being	sent:

		    {'UP', reference(),	driver,	Name, loaded}:
		      This message is sent either immediately if the driver is
		      already  loaded  and  no	reloading  is pending, or when
		      reloading	is executed if reloading is pending.

		      The user is expected to know if  reloading  is  demanded
		      before creating a	monitor	for loading.

		    {'UP', reference(),	driver,	Name, permanent}:
		      This  message is sent if reloading was expected, but the
		      (old) driver made	itself permanent before	reloading.  It
		      is  also	sent if	the driver was permanent or statically
		      linked-in	when trying to create the monitor.

		    {'DOWN', reference(), driver, Name,	load_cancelled}:
		      This message arrives if reloading	was underway, but  the
		      requesting user cancelled	it by dying or calling try_un-
		      load/2 (or unload/1/unload_driver/1) again before	it was
		      reloaded.

		    {'DOWN',  reference(),  driver, Name, {load_failure, Fail-
		    ure}}:
		      This message arrives if reloading	was underway  but  the
		      loading  for some	reason failed. The Failure term	is one
		      of the errors that can be	returned from try_load/3.  The
		      error  term can be passed	to format_error/1 for transla-
		      tion into	human readable form. Notice that the  transla-
		      tion must	be done	in the same running Erlang virtual ma-
		      chine as the error was detected in.

		  unloaded:
		    Monitors when a driver gets	unloaded. If  one  monitors  a
		    driver  that is not	present	in the system, one immediately
		    gets notified that the driver got unloaded.	 There	is  no
		    guarantee that the driver was ever loaded.

		    A  driver  monitor for unload eventually results in	one of
		    the	following messages being sent:

		    {'DOWN', reference(), driver, Name,	unloaded}:
		      The monitored driver instance is now  unloaded.  As  the
		      unload can be a result of	a reload/2 request, the	driver
		      can once again have been loaded when  this  message  ar-
		      rives.

		    {'UP', reference(),	driver,	Name, unload_cancelled}:
		      This  message  is	 sent  if  unloading was expected, but
		      while the	driver	was  waiting  for  all	ports  to  get
		      closed,  a  new user of the driver appeared, and the un-
		      loading was cancelled.

		      This message appears if  {ok,  pending_driver}  was  re-
		      turned  from  try_unload/2  for  the  last  user	of the
		      driver, and then {ok, already_loaded} is returned	from a
		      call to try_load/3.

		      If  one really wants to monitor when the driver gets un-
		      loaded, this message distorts the	 picture,  because  no
		      unloading	was done. Option unloaded_only creates a moni-
		      tor similar to an	unloaded monitor, but never results in
		      this message.

		    {'UP', reference(),	driver,	Name, permanent}:
		      This  message is sent if unloading was expected, but the
		      driver made itself permanent  before  unloading.	It  is
		      also sent	if trying to monitor a permanent or statically
		      linked-in	driver.

		  unloaded_only:
		    A monitor created as unloaded_only behaves exactly as  one
		    created  as	 unloaded  except that the {'UP', reference(),
		    driver, Name, unload_cancelled} message is never sent, but
		    the	 monitor instead persists until	the driver really gets
		    unloaded.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       reload(Path, Name) -> ok	| {error, ErrorDesc}

	      Types:

		 Path =	path()
		 Name =	driver()
		 ErrorDesc = pending_process | OpaqueError
		 OpaqueError = term()

	      Reloads  the  driver  named  Name	from a possibly	different Path
	      than previously used. This function is used in the  code	change
	      scenario described in the	introduction.

	      If  there	 are  other users of this driver, the function returns
	      {error, pending_process},	but if there are no other  users,  the
	      function call hangs until	all open ports are closed.

	  Note:
	      Avoid mixing multiple users with driver reload requests.

	      To avoid hanging on open ports, use function try_load/3 instead.

	      The  Name	 and  Path parameters have exactly the same meaning as
	      when calling the plain function load/2.

	      On success, the function returns ok. On  failure,	 the  function
	      returns  an  opaque  error, except the pending_process error de-
	      scribed earlier. The opaque errors are to	be translated into hu-
	      man readable form	by function format_error/1.

	      For more control over the	error handling,	use the	try_load/3 in-
	      terface instead.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       reload_driver(Path, Name) -> ok | {error, ErrorDesc}

	      Types:

		 Path =	path()
		 Name =	driver()
		 ErrorDesc = pending_process | OpaqueError
		 OpaqueError = term()

	      Works  exactly  as  reload/2,  but  for  drivers loaded with the
	      load_driver/2 interface.

	      As this interface	implies	that ports are killed  when  the  last
	      user disappears, the function does not hang waiting for ports to
	      get closed.

	      For more details,	see scenarios in this module  description  and
	      the function description for reload/2.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       try_load(Path, Name, OptionList)	->
		   {ok,	Status}	|
		   {ok,	PendingStatus, Ref} |
		   {error, ErrorDesc}

	      Types:

		 Path =	path()
		 Name =	driver()
		 OptionList = [Option]
		 Option	=
		     {driver_options, DriverOptionList}	|
		     {monitor, MonitorOption} |
		     {reload, ReloadOption}
		 DriverOptionList = [DriverOption]
		 DriverOption =	kill_ports
		 MonitorOption = ReloadOption =	pending_driver | pending
		 Status	= loaded | already_loaded | PendingStatus
		 PendingStatus = pending_driver	| pending_process
		 Ref = reference()
		 ErrorDesc = ErrorAtom | OpaqueError
		 ErrorAtom =
		     linked_in_driver |
		     inconsistent |
		     permanent |
		     not_loaded_by_this_process	|
		     not_loaded	|
		     pending_reload |
		     pending_process
		 OpaqueError = term()

	      Provides	 more	control	  than	 the	load/2/reload/2	   and
	      load_driver/2/reload_driver/2  interfaces.  It  never  waits for
	      completion of other operations related to	the driver, but	 imme-
	      diately  returns	the status of the driver as one	of the follow-
	      ing:

		{ok, loaded}:
		  The driver was loaded	and is immediately usable.

		{ok, already_loaded}:
		  The driver was already loaded	by another process  or	is  in
		  use by a living port,	or both. The load by you is registered
		  and a	corresponding try_unload is expected sometime  in  the
		  future.

		{ok, pending_driver}or {ok, pending_driver, reference()}:
		  The  load  request is	registered, but	the loading is delayed
		  because an earlier instance of the driver is	still  waiting
		  to  get  unloaded  (open ports use it). Still, unload	is ex-
		  pected when you are done with	the driver. This return	 value
		  mostly   occurs   when  options  {reload,pending_driver}  or
		  {reload,pending} are used, but can occur when	 another  user
		  is   unloading  a  driver  in	 parallel  and	driver	option
		  kill_ports is	set. In	other words, this return value	always
		  needs	to be handled.

		{ok, pending_process}or	{ok, pending_process, reference()}:
		  The  load  request is	registered, but	the loading is delayed
		  because an earlier instance of the driver is	still  waiting
		  to  get  unloaded  by	 another  user (not only by a port, in
		  which	case {ok,pending_driver} would	have  been  returned).
		  Still, unload	is expected when you are done with the driver.
		  This return value only occurs	when  option  {reload,pending}
		  is used.

	      When  the	 function  returns  {ok, pending_driver} or {ok, pend-
	      ing_process}, one	can get	information about when the  driver  is
	      actually loaded by using option {monitor,	MonitorOption}.

	      When  monitoring	is  requested,	and a corresponding {ok, pend-
	      ing_driver} or {ok,  pending_process}  would  be	returned,  the
	      function	instead	 returns  a  tuple  {ok, PendingStatus,	refer-
	      ence()} and the process then gets	a monitor message later,  when
	      the  driver  gets	 loaded.  The monitor message to expect	is de-
	      scribed in the function description of monitor/2.

	  Note:
	      In case of loading, monitoring can not only get triggered	by us-
	      ing  option  {reload,  ReloadOption},  but also in special cases
	      where  the  load	error  is  transient.  Thus,  {monitor,	 pend-
	      ing_driver} is to	be used	under basically	all real world circum-
	      stances.

	      The function accepts the following parameters:

		Path:
		  The file system path to the directory	where the  driver  ob-
		  ject file is located.	The filename of	the object file	(minus
		  extension) must correspond to	the driver name	(used  in  pa-
		  rameter  Name)  and the driver must identify itself with the
		  same name. Path can be provided as an	iolist(),  meaning  it
		  can  be  a  list of other iolist()s, characters (8-bit inte-
		  gers), or binaries, all to be	flattened into a  sequence  of
		  characters.

		  The  (possibly  flattened) Path parameter must be consistent
		  throughout the system. A driver is  to,  by  all  users,  be
		  loaded  using	 the  same literal Path. The exception is when
		  reloading is requested, in which case	Path can be  specified
		  differently. Notice that all users trying to load the	driver
		  later	need to	use the	new Path if Path is  changed  using  a
		  reload  option.  This	is yet another reason to have only one
		  loader of a driver one wants to upgrade in a running system.

		Name:
		  This parameter is the	name of	the driver to be used in  sub-
		  sequent calls	to function erlang:open_port in	ERTS. The name
		  can be specified as an iolist() or an	atom().	The name spec-
		  ified	when loading is	used to	find the object	file (with the
		  help of Path and the system-implied extension	 suffix,  that
		  is,  .so).  The  name	 by which the driver identifies	itself
		  must also be consistent with this Name  parameter,  much  as
		  the module name of a Beam file much corresponds to its file-
		  name.

		OptionList:
		  Some options can be specified	to control the loading	opera-
		  tion.	The options are	specified as a list of two-tuples. The
		  tuples have the following values and meanings:

		  {driver_options, DriverOptionList}:
		    This is to provide options that changes its	general	behav-
		    ior	and "sticks" to	the driver throughout its lifespan.

		    The	driver options for a specified driver name need	always
		    to be consistent, even when	the driver is reloaded,	 mean-
		    ing	 that  they  are  as  much a part of the driver	as the
		    name.

		    The	only allowed driver option is kill_ports, which	 means
		    that  all  ports opened to the driver are killed with exit
		    reason driver_unloaded when	no process any longer has  the
		    driver  loaded. This situation arises either when the last
		    user calls try_unload/2, or	when the last  process	having
		    loaded the driver exits.

		  {monitor, MonitorOption}:
		    A MonitorOption tells try_load/3 to	trigger	a driver moni-
		    tor	under certain conditions. When the  monitor  is	 trig-
		    gered, the function	returns	a three-tuple {ok, PendingSta-
		    tus, reference()}, where reference() is the	monitor	refer-
		    ence for the driver	monitor.

		    Only  one MonitorOption can	be specified. It is one	of the
		    following:

		    * The atom pending,	which means that a monitor  is	to  be
		      created whenever a load operation	is delayed,

		    * The  atom	 pending_driver, in which a monitor is created
		      whenever the operation is	delayed	because	of open	 ports
		      to an otherwise unused driver.

		    Option pending_driver is of	little use, but	is present for
		    completeness, as it	is well	defined	which  reload  options
		    that  can  give rise to which delays. However, it can be a
		    good idea to use the same MonitorOption as	the  ReloadOp-
		    tion, if present.

		    If	reloading  is not requested, it	can still be useful to
		    specify option monitor, as forced unloads  (driver	option
		    kill_ports or option kill_ports to try_unload/2) trigger a
		    transient state where driver loading cannot	 be  performed
		    until  all	closing	 ports are closed. Thus, as try_unload
		    can,  in  almost  all  situations,	 return	  {ok,	 pend-
		    ing_driver},  always  specify  at  least  {monitor,	 pend-
		    ing_driver}	in production code (see	the monitor discussion
		    earlier).

		  {reload, ReloadOption}:
		    This option	is used	to reload a driver from	disk, most of-
		    ten	in a code upgrade scenario.  Having  a	reload	option
		    also  implies that parameter Path does not need to be con-
		    sistent with earlier loads of the driver.

		    To reload a	driver,	 the  process  must  have  loaded  the
		    driver  before,  that  is, there must be an	active user of
		    the	driver in the process.

		    The	reload option can be either of the following:

		    pending:
		      With the atom pending, reloading is  requested  for  any
		      driver  and  is effectuated when all ports opened	to the
		      driver are closed. The driver replacement	in  this  case
		      takes  place regardless if there are still pending users
		      having the driver	loaded.

		      The option also triggers port-killing (if	driver	option
		      kill_ports  is  used)  although there are	pending	users,
		      making it	usable for forced driver replacement, but lay-
		      ing much responsibility on the driver users. The pending
		      option is	seldom used as one does	not want  other	 users
		      to have loaded the driver	when code change is underway.

		    pending_driver:
		      This option is more useful. Here,	reloading is queued if
		      the driver is not	loaded by any  other  users,  but  the
		      driver  has  opened  ports,  in  which  case  {ok, pend-
		      ing_driver} is returned  (a  monitor  option  is	recom-
		      mended).

		    If the driver is unloaded (not present in the system), er-
		    ror	code not_loaded	is returned. Option reload is intended
		    for	 when  the  user  has already loaded the driver	in ad-
		    vance.

	      The function can return numerous errors, some can	 only  be  re-
	      turned given a certain combination of options.

	      Some  errors  are	 opaque	and can	only be	interpreted by passing
	      them to function format_error/1, but some	can be interpreted di-
	      rectly:

		{error,linked_in_driver}:
		  The  driver  with the	specified name is an Erlang statically
		  linked-in driver, which cannot be manipulated	with this API.

		{error,inconsistent}:
		  The driver is	already	loaded with other DriverOptionList  or
		  a different literal Path argument.

		  This	can  occur  even  if  a	reload option is specified, if
		  DriverOptionList differs from	the current.

		{error,	permanent}:
		  The driver has requested itself to be	permanent,  making  it
		  behave  like an Erlang linked-in driver and can no longer be
		  manipulated with this	API.

		{error,	pending_process}:
		  The driver is	loaded by other	 users	when  option  {reload,
		  pending_driver} was specified.

		{error,	pending_reload}:
		  Driver  reload is already requested by another user when op-
		  tion {reload,	ReloadOption} was specified.

		{error,	not_loaded_by_this_process}:
		  Appears when option reload is	specified. The driver Name  is
		  present  in  the  system, but	there is no user of it in this
		  process.

		{error,	not_loaded}:
		  Appears when option reload is	specified. The driver Name  is
		  not  in  the system. Only drivers loaded by this process can
		  be reloaded.

	      All other	error codes are	to  be	translated  by	function  for-
	      mat_error/1.  Notice  that  calls	to format_error	are to be per-
	      formed from the same running instance of the Erlang virtual  ma-
	      chine  as	 the error is detected in, because of system-dependent
	      behavior concerning error	values.

	      If the arguments or options are malformed, the function throws a
	      badarg exception.

       try_unload(Name,	OptionList) ->
		     {ok, Status} |
		     {ok, PendingStatus, Ref} |
		     {error, ErrorAtom}

	      Types:

		 Name =	driver()
		 OptionList = [Option]
		 Option	= {monitor, MonitorOption} | kill_ports
		 MonitorOption = pending_driver	| pending
		 Status	= unloaded | PendingStatus
		 PendingStatus = pending_driver	| pending_process
		 Ref = reference()
		 ErrorAtom =
		     linked_in_driver |
		     not_loaded	|
		     not_loaded_by_this_process	|
		     permanent

	      This is the low-level function to	unload (or decrement reference
	      counts of) a driver. It can be used to force  port  killing,  in
	      much  the	 same  way  as the driver option kill_ports implicitly
	      does. Also, it can trigger a monitor either because other	 users
	      still  have  the	driver	loaded	or  because open ports use the
	      driver.

	      Unloading	can be described as the	process	of telling the	emula-
	      tor  that	 this  particular  part	of the code in this particular
	      process (that is,	this user) no longer needs  the	 driver.  That
	      can,  if	there  are  no	other  users, trigger unloading	of the
	      driver, in which case the	driver name disappears from the	system
	      and  (if	possible) the memory occupied by the driver executable
	      code is reclaimed.

	      If the driver has	option kill_ports set,	or  if	kill_ports  is
	      specified	as an option to	this function, all pending ports using
	      this driver are killed when unloading is done by the last	 user.
	      If no port-killing is involved and there are open	ports, the un-
	      loading is delayed until no more open ports use the driver.  If,
	      in  this case, another user (or even this	user) loads the	driver
	      again before the driver is unloaded, the unloading  never	 takes
	      place.

	      To  allow	 the  user to request unloading	to wait	for actual un-
	      loading, monitor triggers	can be specified in much the same  way
	      as  when	loading. However, as users of this function seldom are
	      interested in more than decrementing the reference counts, moni-
	      toring is	seldom needed.

	  Note:
	      If  option  kill_ports  is used, monitor trigging	is crucial, as
	      the ports	are not	guaranteed to be killed	until  the  driver  is
	      unloaded.	 Thus,	a  monitor  must be triggered for at least the
	      pending_driver case.

	      The possible monitor messages to expect are the same as when us-
	      ing option unloaded to function monitor/2.

	      The function returns one of the following	statuses upon success:

		{ok, unloaded}:
		  The driver was immediately unloaded, meaning that the	driver
		  name is now free to use by other drivers and,	if the	under-
		  lying	 OS  permits it, the memory occupied by	the driver ob-
		  ject code is now reclaimed.

		  The driver can only be unloaded when there are no open ports
		  using	it and no more users require it	to be loaded.

		{ok, pending_driver}or {ok, pending_driver, reference()}:
		  Indicates  that  this	 call  removed	the last user from the
		  driver, but there are	still open ports using	it.  When  all
		  ports	 are  closed and no new	users have arrived, the	driver
		  is reloaded and the name and memory reclaimed.

		  This return value is valid even  if  option  kill_ports  was
		  used,	 as  killing ports can be a process that does not com-
		  plete	immediately. However, the condition is	in  that  case
		  transient.  Monitors	are  always  useful to detect when the
		  driver is really unloaded.

		{ok, pending_process}or	{ok, pending_process, reference()}:
		  The unload request is	registered, but	other users still hold
		  the  driver.	Notice that the	term pending_process can refer
		  to the running process; there	can be more than one  user  in
		  the same process.

		  This is a normal, healthy, return value if the call was just
		  placed to inform the emulator	that you have no  further  use
		  of  the  driver.  It	is the most common return value	in the
		  most common scenario described in the	introduction.

	      The function accepts the following parameters:

		Name:
		  Name is the name of the driver to be unloaded. The name  can
		  be specified as an iolist() or as an atom().

		OptionList:
		  Argument  OptionList can be used to specify certain behavior
		  regarding ports and triggering monitors under	certain	condi-
		  tions:

		  kill_ports:
		    Forces killing of all ports	opened using this driver, with
		    exit reason	driver_unloaded, if you	are the	last  user  of
		    the	driver.

		    If	other users have the driver loaded, this option	has no
		    effect.

		    To get the consistent behavior of killing ports  when  the
		    last user unloads, use driver option kill_ports when load-
		    ing	the driver instead.

		  {monitor, MonitorOption}:
		    Creates a driver monitor if	 the  condition	 specified  in
		    MonitorOption is true. The valid options are:

		    pending_driver:
		      Creates  a  driver  monitor if the return	value is to be
		      {ok, pending_driver}.

		    pending:
		      Creates a	monitor	if the	return	value  is  {ok,	 pend-
		      ing_driver} or {ok, pending_process}.

		    The	 pending_driver	 MonitorOption is by far the most use-
		    ful. It must be used to ensure that	the driver  really  is
		    unloaded  and  the ports closed whenever option kill_ports
		    is used, or	the driver can have been  loaded  with	driver
		    option kill_ports.

		    Using  the	monitor	triggers in the	call to	try_unload en-
		    sures that the monitor is added before  the	 unloading  is
		    executed,  meaning	that  the  monitor  is always properly
		    triggered, which is	not the	case if	 monitor/2  is	called
		    separately.

	      The function can return the following error conditions, all well
	      specified	(no opaque values):

		{error,	linked_in_driver}:
		  You were trying to unload  an	 Erlang	 statically  linked-in
		  driver, which	cannot be manipulated with this	interface (and
		  cannot be unloaded at	all).

		{error,	not_loaded}:
		  The driver Name is not present in the	system.

		{error,	not_loaded_by_this_process}:
		  The driver Name is present in	the system, but	 there	is  no
		  user of it in	this process.

		  As  a	 special  case,	drivers	can be unloaded	from processes
		  that have done no corresponding call to try_load/3  if,  and
		  only	if, there are no users of the driver at	all, which can
		  occur	if the process containing the last user	dies.

		{error,	permanent}:
		  The driver has made itself permanent,	in which case  it  can
		  no  longer  be  manipulated  by  this	interface (much	like a
		  statically linked-in driver).

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       unload(Name) -> ok | {error, ErrorDesc}

	      Types:

		 Name =	driver()
		 ErrorDesc = term()

	      Unloads,	or at least dereferences the driver named Name.	If the
	      caller is	the last user of the driver, and no  more  open	 ports
	      use  the	driver,	the driver gets	unloaded. Otherwise, unloading
	      is delayed until all ports are closed and	no users remain.

	      If there are other users of the driver, the reference counts  of
	      the  driver is merely decreased, so that the caller is no	longer
	      considered a user	of the driver. For use scenarios, see the  de-
	      scription	in the beginning of this module.

	      The  ErrorDesc  returned is an opaque value to be	passed further
	      on to function format_error/1. For more control over the	opera-
	      tion, use	the try_unload/2 interface.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

       unload_driver(Name) -> ok | {error, ErrorDesc}

	      Types:

		 Name =	driver()
		 ErrorDesc = term()

	      Unloads, or at least dereferences	the driver named Name. If  the
	      caller  is the last user of the driver, all remaining open ports
	      using the	driver are killed with reason driver_unloaded and  the
	      driver eventually	gets unloaded.

	      If  there	are other users	of the driver, the reference counts of
	      the driver is merely decreased, so that the caller is no	longer
	      considered a user. For use scenarios, see	the description	in the
	      beginning	of this	module.

	      The ErrorDesc returned is	an opaque value	to be  passed  further
	      on  to function format_error/1. For more control over the	opera-
	      tion, use	the try_unload/2 interface.

	      The function throws a badarg exception if	the parameters are not
	      specified	as described here.

SEE ALSO
       erts:erl_driver(4), erts:driver_entry(4)

Ericsson AB			  kernel 6.3			   erl_ddll(3)

NAME | DESCRIPTION | DATA TYPES | EXPORTS | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=erl_ddll&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help