aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2014-01-28 15:09:35 +0100
committerHans Nilsson <[email protected]>2014-01-28 15:09:35 +0100
commitdc7eeae35b5a9e23a08584605e71c4007dfd74ee (patch)
treeb5db58006d3c7f676105310074d7961e8952b127
parent6de916efa8df952ca1e24cccda673134982c0da0 (diff)
parent9ec3ad0d292a5b89a332cb24ed2246a3bfdf9443 (diff)
downloadotp-dc7eeae35b5a9e23a08584605e71c4007dfd74ee.tar.gz
otp-dc7eeae35b5a9e23a08584605e71c4007dfd74ee.tar.bz2
otp-dc7eeae35b5a9e23a08584605e71c4007dfd74ee.zip
Merge branch 'master' of super:otp
-rw-r--r--erts/doc/src/erl_driver.xml28
-rw-r--r--erts/emulator/beam/erl_async.c22
-rw-r--r--erts/emulator/beam/erl_driver.h10
-rw-r--r--erts/emulator/sys/win32/erl_win_dyn_driver.h4
-rw-r--r--erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c4
-rw-r--r--erts/emulator/test/driver_SUITE_data/otp_9302_drv.c2
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c4
-rw-r--r--erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c4
-rw-r--r--lib/public_key/doc/src/public_key.xml49
-rw-r--r--lib/public_key/include/public_key.hrl3
-rw-r--r--lib/ssh/src/ssh.erl4
-rw-r--r--lib/ssl/src/ssl_connection.hrl2
-rw-r--r--lib/ssl/src/ssl_handshake.erl6
-rw-r--r--lib/ssl/src/ssl_internal.hrl1
-rw-r--r--system/doc/reference_manual/code_loading.xml7
15 files changed, 48 insertions, 102 deletions
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index b453a4861e..c2f7fa4588 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -745,7 +745,7 @@ typedef struct ErlIOVec {
created and decrement it once when the port associated with
the lock terminates. The emulator will also increment the
reference count when an async job is enqueued and decrement
- it after an async job has been invoked, or canceled. Besides
+ it after an async job has been invoked. Besides
this, it is the responsibility of the driver to ensure that
the reference count does not reach zero before the last use
of the lock by the driver has been made. The reference count
@@ -1995,14 +1995,12 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
<c>async_invoke</c> and <c>async_free</c>. It's typically a
pointer to a structure that contains a pipe or event that
can be used to signal that the async operation completed.
- The data should be freed in <c>async_free</c>, because it's
- called if <c>driver_async_cancel</c> is called.</p>
+ The data should be freed in <c>async_free</c>.</p>
<p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver
entry function is called. If <c>ready_async</c> is null in
the driver entry, the <c>async_free</c> function is called
instead.</p>
- <p>The return value is a handle to the asynchronous task, which
- can be used as argument to <c>driver_async_cancel</c>.</p>
+ <p>The return value is a handle to the asynchronous task.</p>
<note>
<p>As of erts version 5.5.4.3 the default stack size for
threads in the async-thread pool is 16 kilowords,
@@ -2040,26 +2038,6 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len
</desc>
</func>
<func>
- <name><ret>int</ret><nametext>driver_async_cancel(long id)</nametext></name>
- <fsummary>Cancel an asynchronous call</fsummary>
- <desc>
- <marker id="driver_async_cancel"></marker>
- <p>This function used to cancel a scheduled asynchronous operation,
- if it was still in the queue. It returned 1 if it succeeded, and
- 0 if it failed.</p>
- <p>Since it could not guarantee success, it was more or less useless.
- The user had to implement synchronization of cancellation anyway.
- It also unnecessarily complicated the implementation. Therefore,
- as of OTP-R15B <c>driver_async_cancel()</c> is deprecated, and
- scheduled for removal in OTP-R17. It will currently always fail,
- and return 0.</p>
- <warning><p><c>driver_async_cancel()</c> is deprecated and will
- be removed in the OTP-R17 release.</p>
- </warning>
-
- </desc>
- </func>
- <func>
<name><ret>int</ret><nametext>driver_lock_driver(ErlDrvPort port)</nametext></name>
<fsummary>Make sure the driver is never unloaded</fsummary>
<desc>
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index e6d72f569b..f0cec1c53c 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -602,7 +602,7 @@ unsigned int driver_async_port_key(ErlDrvPort port)
** return values:
** 0 completed
** -1 error
-** N handle value (used with async_cancel)
+** N handle value
** arguments:
** ix driver index
** key pointer to secedule queue (NULL means round robin)
@@ -687,23 +687,3 @@ long driver_async(ErlDrvPort ix, unsigned int* key,
return id;
}
-
-int driver_async_cancel(unsigned int id)
-{
- /*
- * Not supported anymore. Always fail (which is backward
- * compatible).
- *
- * This functionality could be implemented again. However,
- * it is (and always has been) completely useless since
- * it doesn't give you any guarantees whatsoever. The user
- * needs to (and always have had to) synchronize in his/her
- * own code in order to get any guarantees.
- */
- return 0;
-}
-
-
-
-
-
diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h
index 5cffae92be..2bd3181bdc 100644
--- a/erts/emulator/beam/erl_driver.h
+++ b/erts/emulator/beam/erl_driver.h
@@ -132,8 +132,8 @@ typedef struct {
#define DO_WRITE ERL_DRV_WRITE
#define ERL_DRV_EXTENDED_MARKER (0xfeeeeeed)
-#define ERL_DRV_EXTENDED_MAJOR_VERSION 2
-#define ERL_DRV_EXTENDED_MINOR_VERSION 2
+#define ERL_DRV_EXTENDED_MAJOR_VERSION 3
+#define ERL_DRV_EXTENDED_MINOR_VERSION 0
/*
* The emulator will refuse to load a driver with different major
@@ -657,12 +657,6 @@ EXTERN long driver_async(ErlDrvPort ix,
void* async_data,
void (*async_free)(void*));
-/*
- * driver_async_cancel() is deprecated. It is scheduled for removal
- * in OTP-R16. For more information see the erl_driver(3) documentation.
- */
-EXTERN int driver_async_cancel(unsigned int key) ERL_DRV_DEPRECATED_FUNC;
-
/* Locks the driver in the machine "forever", there is
no unlock function. Note that this is almost never useful, as an open
port towards the driver locks it until the port is closed, why unexpected
diff --git a/erts/emulator/sys/win32/erl_win_dyn_driver.h b/erts/emulator/sys/win32/erl_win_dyn_driver.h
index b9a9838a36..4010d939e5 100644
--- a/erts/emulator/sys/win32/erl_win_dyn_driver.h
+++ b/erts/emulator/sys/win32/erl_win_dyn_driver.h
@@ -82,7 +82,6 @@ WDD_TYPEDEF(int, erl_drv_send_term, (ErlDrvTermData, ErlDrvTermData, ErlDrvTermD
WDD_TYPEDEF(int, driver_send_term, (ErlDrvPort, ErlDrvTermData, ErlDrvTermData*, int));
WDD_TYPEDEF(unsigned int, driver_async_port_key, (ErlDrvPort));
WDD_TYPEDEF(long, driver_async, (ErlDrvPort,unsigned int*,void (*)(void*),void*,void (*)(void*)));
-WDD_TYPEDEF(int, driver_async_cancel, (unsigned int));
WDD_TYPEDEF(int, driver_lock_driver, (ErlDrvPort));
WDD_TYPEDEF(void *, driver_dl_open, (char *));
WDD_TYPEDEF(void *, driver_dl_sym, (void *, char *));
@@ -200,7 +199,6 @@ typedef struct {
WDD_FTYPE(driver_send_term) *driver_send_term;
WDD_FTYPE(driver_async_port_key) *driver_async_port_key;
WDD_FTYPE(driver_async) *driver_async;
- WDD_FTYPE(driver_async_cancel) *driver_async_cancel;
WDD_FTYPE(driver_lock_driver) *driver_lock_driver;
WDD_FTYPE(driver_dl_open) *driver_dl_open;
WDD_FTYPE(driver_dl_sym) *driver_dl_sym;
@@ -312,7 +310,6 @@ extern TWinDynDriverCallbacks WinDynDriverCallbacks;
#define driver_send_term (WinDynDriverCallbacks.driver_send_term)
#define driver_async_port_key (WinDynDriverCallbacks.driver_async_port_key)
#define driver_async (WinDynDriverCallbacks.driver_async)
-#define driver_async_cancel (WinDynDriverCallbacks.driver_async_cancel)
#define driver_lock_driver (WinDynDriverCallbacks.driver_lock_driver)
#define driver_dl_open (WinDynDriverCallbacks.driver_dl_open)
#define driver_dl_sym (WinDynDriverCallbacks.driver_dl_sym)
@@ -448,7 +445,6 @@ do { \
((W).driver_send_term) = driver_send_term; \
((W).driver_async_port_key) = driver_async_port_key; \
((W).driver_async) = driver_async; \
-((W).driver_async_cancel) = driver_async_cancel; \
((W).driver_lock_driver) = driver_lock_driver; \
((W).driver_dl_open) = driver_dl_open; \
((W).driver_dl_sym) = driver_dl_sym; \
diff --git a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
index 9d8bbac231..e2b338f801 100644
--- a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c
@@ -277,10 +277,6 @@ static void stop(ErlDrvData drv_data)
case IOQ_EXIT_TIMEOUT_ASYNC:
driver_cancel_timer(ddp->port);
break;
- case IOQ_EXIT_READY_ASYNC:
- if (ddp->outstanding_async_task)
- driver_async_cancel(ddp->async_task);
- break;
default:
break;
}
diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
index 88df73f696..7c144d20cf 100644
--- a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c
@@ -227,6 +227,4 @@ static void output(ErlDrvData drv_data,
ad[4]->term_data.msg = driver_mk_atom("end_of_jobs");
for (i = 0; i < sizeof(id)/sizeof(id[0]); i++)
id[i] = driver_async(data->port, &key, async_invoke, ad[i], driver_free);
- if (id[2] > 0)
- driver_async_cancel(id[2]);
}
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c
index c22a415c59..e44c7dbd5e 100644
--- a/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c
@@ -19,14 +19,14 @@
/*
* Author: Rickard Green
*
- * Description: Driver that fakes driver version 2.0 and tests
+ * Description: Driver that fakes driver version 3.0 and tests
* driver_system_info().
*
*/
#include "sys_info_drv_impl.h"
-#define SYS_INFO_DRV_MAJOR_VSN 2
+#define SYS_INFO_DRV_MAJOR_VSN 3
#define SYS_INFO_DRV_MINOR_VSN 0
#define SYS_INFO_DRV_NAME_STR "sys_info_base_drv"
#define SYS_INFO_DRV_NAME sys_info_base_drv
diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c
index 815d96cc97..63c69f751c 100644
--- a/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c
+++ b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c
@@ -19,14 +19,14 @@
/*
* Author: Rickard Green
*
- * Description: Driver that fakes driver version 2.0 and tests
+ * Description: Driver that fakes driver version 3.0 and tests
* driver_system_info().
*
*/
#include "sys_info_drv_impl.h"
-#define SYS_INFO_DRV_MAJOR_VSN 2
+#define SYS_INFO_DRV_MAJOR_VSN 3
#define SYS_INFO_DRV_MINOR_VSN 0
#define SYS_INFO_DRV_NAME_STR "sys_info_prev_drv"
#define SYS_INFO_DRV_NAME sys_info_prev_drv
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index 002f641f1d..bd19d0e434 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -71,7 +71,7 @@
<p>Use the following include directive to get access to the
records and constant macros described here and in the User's Guide.</p>
- <code> -include_lib("public_key/include/public_key.hrl"). </code>
+ <code> -include_lib("public_key/include/public_key.hrl").</code>
<p><em>Data Types </em></p>
@@ -84,44 +84,49 @@
<p><code>der_encoded() = binary()</code></p>
<p><code>pki_asn1_type() = 'Certificate' | 'RSAPrivateKey'| 'RSAPublicKey' |
- 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' | 'SubjectPublicKeyInfo' |
- 'PrivateKeyInfo' | 'CertificationRequest' | 'ECPrivateKey'|
- 'EcpkParameters'</code></p>
+ 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' |
+ 'SubjectPublicKeyInfo' | 'PrivateKeyInfo' |
+ 'CertificationRequest' | 'ECPrivateKey' | 'EcpkParameters'</code></p>
<p><code>pem_entry () = {pki_asn1_type(), binary(), %% DER or encrypted DER
- not_encrypted | cipher_info()} </code></p>
+ not_encrypted | cipher_info()}</code></p>
- <p><code>cipher_info() = {"RC2-CBC | "DES-CBC" | "DES-EDE3-CBC", crypto:rand_bytes(8)} |
- 'PBES2-params'} </code></p>
+ <p><code>cipher_info() = {"RC2-CBC | "DES-CBC" | "DES-EDE3-CBC",
+ crypto:rand_bytes(8)} | 'PBES2-params'}</code></p>
+ <p><code>public_key() = rsa_public_key() | dsa_public_key() | ec_public_key()</code></p>
+ <p><code>private_key() = rsa_public_key() | dsa_public_key() | ec_public_key()</code></p>
<p><code>rsa_public_key() = #'RSAPublicKey'{}</code></p>
- <p><code>rsa_private_key() = #'RSAPrivateKey'{} </code></p>
+ <p><code>rsa_private_key() = #'RSAPrivateKey'{}</code></p>
- <p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}} </code></p>
+ <p><code>dsa_public_key() = {integer(), #'Dss-Parms'{}}</code></p>
<p><code>dsa_private_key() = #'DSAPrivateKey'{}</code></p>
- <p><code>ec_public_key() = {#'ECPoint'{}, #'EcpkParameters'{} | {namedCurve, oid()}} </code></p>
+ <p><code>ec_public_key() = {#'ECPoint'{}, #'EcpkParameters'{} |
+ {namedCurve, oid()}}</code></p>
<p><code>ec_private_key() = #'ECPrivateKey'{}</code></p>
- <p><code> public_crypt_options() = [{rsa_pad, rsa_padding()}]. </code></p>
+ <p><code>public_crypt_options() = [{rsa_pad, rsa_padding()}].</code></p>
- <p><code> rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
- | 'rsa_no_padding'</code></p>
+ <p><code>rsa_padding() = 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' |
+ 'rsa_no_padding'</code></p>
- <p><code> rsa_digest_type() = 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512' </code></p>
+ <p><code>rsa_digest_type() = 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' |
+ 'sha512'</code></p>
- <p><code> dss_digest_type() = 'sha' </code></p>
+ <p><code>dss_digest_type() = 'sha'</code></p>
- <p><code> ecdsa_digest_type() = 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512' </code></p>
+ <p><code>ecdsa_digest_type() = 'sha'| 'sha224' | 'sha256' | 'sha384' | 'sha512'</code></p>
- <p><code> crl_reason() = unspecified | keyCompromise | cACompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise
- </code></p>
+ <p><code>crl_reason() = unspecified | keyCompromise | cACompromise |
+ affiliationChanged | superseded | cessationOfOperation |
+ certificateHold | privilegeWithdrawn | aACompromise</code></p>
- <p><code> ssh_file() = openssh_public_key | rfc4716_public_key |
- known_hosts | auth_keys </code></p>
+ <p><code>ssh_file() = openssh_public_key | rfc4716_public_key | known_hosts |
+ auth_keys</code></p>
<!-- <p><code>policy_tree() = [Root, Children]</code></p> -->
@@ -430,7 +435,7 @@
constructing the input to this function and that should be run through the <c>verify_fun</c>.</d>
<v> CertChain = [der_encode()]</v>
<d>A list of DER encoded certificates in trust order ending with the peer certificate.</d>
- <v> Options = proplists:proplists()</v>
+ <v> Options = proplists:proplist()</v>
<v>PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa',
rsa_public_key() | integer(), 'NULL' | 'Dss-Parms'{}}</v>
<v> PolicyTree = term() </v>
@@ -492,7 +497,7 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<type>
<v> OTPCertificate = #'OTPCertificate'{}</v>
<v> DPAndCRLs = [{DP::#'DistributionPoint'{} ,CRL::#'CertificateList'{}}] </v>
- <v> Options = proplists:proplists()</v>
+ <v> Options = proplists:proplist()</v>
<v> CRLStatus() = valid | {bad_cert, revocation_status_undetermined} |
{bad_cert, {revoked, crl_reason()}}</v>
</type>
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 1e882e76ee..8afc841fa6 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -88,7 +88,8 @@
-define(privilegeWithdrawn, 9).
-define(aACompromise, 10).
--type public_key() :: rsa_public_key() | dsa_public_key().
+-type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key().
+-type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key().
-type rsa_public_key() :: #'RSAPublicKey'{}.
-type rsa_private_key() :: #'RSAPrivateKey'{}.
-type dsa_private_key() :: #'DSAPrivateKey'{}.
diff --git a/lib/ssh/src/ssh.erl b/lib/ssh/src/ssh.erl
index 2685b1553b..9f571adba2 100644
--- a/lib/ssh/src/ssh.erl
+++ b/lib/ssh/src/ssh.erl
@@ -59,8 +59,8 @@ stop() ->
application:stop(ssh).
%%--------------------------------------------------------------------
--spec connect(string(), integer(), proplists:proplists()) -> {ok, pid()} | {error, term()}.
--spec connect(string(), integer(), proplists:proplists(), timeout()) -> {ok, pid()} | {error, term()}.
+-spec connect(string(), integer(), proplists:proplist()) -> {ok, pid()} | {error, term()}.
+-spec connect(string(), integer(), proplists:proplist(), timeout()) -> {ok, pid()} | {error, term()}.
%%
%% Description: Starts an ssh connection.
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 27489ca325..adb2e1debe 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -41,7 +41,7 @@
data_tag :: atom(), % ex tcp.
close_tag :: atom(), % ex tcp_closed
error_tag :: atom(), % ex tcp_error
- host :: string() | inet:ipaddress(),
+ host :: string() | inet:ip_address(),
port :: integer(),
socket :: port(),
ssl_options :: #ssl_options{},
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 487dfc01d9..7b4cf8eb06 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -164,7 +164,7 @@ next_protocol(SelectedProtocol) ->
%%--------------------------------------------------------------------
-spec client_certificate_verify(undefined | der_cert(), binary(),
- tls_version(), term(), private_key(),
+ tls_version(), term(), public_key:private_key(),
tls_handshake_history()) ->
#certificate_verify{} | ignore | #alert{}.
%%
@@ -207,12 +207,12 @@ certificate_request(CipherSuite, CertDbHandle, CertDbRef, Version) ->
{premaster_secret, binary(), public_key_info()} |
{dh, binary()} |
{dh, {binary(), binary()}, #'DHParameter'{}, {HashAlgo::atom(), SignAlgo::atom()},
- binary(), binary(), private_key()} |
+ binary(), binary(), public_key:private_key()} |
{ecdh, #'ECPrivateKey'{}} |
{psk, binary()} |
{dhe_psk, binary(), binary()} |
{srp, {binary(), binary()}, #srp_user{}, {HashAlgo::atom(), SignAlgo::atom()},
- binary(), binary(), private_key()}) ->
+ binary(), binary(), public_key:private_key()}) ->
#client_key_exchange{} | #server_key_exchange{}.
%%
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 5a823ec8a4..102215119d 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -35,7 +35,6 @@
-type certdb_ref() :: reference().
-type db_handle() :: term().
-type der_cert() :: binary().
--type private_key() :: #'RSAPrivateKey'{} | #'DSAPrivateKey'{} | #'ECPrivateKey'{}.
-type issuer() :: tuple().
-type serialnumber() :: integer().
-type cert_key() :: {reference(), integer(), issuer()}.
diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml
index 10022a5d33..23871dfa83 100644
--- a/system/doc/reference_manual/code_loading.xml
+++ b/system/doc/reference_manual/code_loading.xml
@@ -121,10 +121,9 @@ loop() ->
<title>Running a function when a module is loaded</title>
<warning>
- <p>This section describes an experimental feature that was
- introduced in R13B03, and changed in a backwards-incompatible
- way in R13B04. There may be more backward-incompatible changes
- in future releases.</p>
+ <p>We recommend that the feature described in this section is to
+ be used only for loading NIF libraries. For other usages this
+ feature should be considered experimental.</p>
</warning>
<p>The <c>-on_load()</c> directive names a function that should