[
Table Of Contents
| Keyword Index
]
ns_proxy(n) 4.99 "NaviServer Modules"
ns_proxy - Execute Tcl scripts in an external process
TABLE OF CONTENTS
SYNOPSIS
DESCRIPTION
COMMANDS
ERROR HANDLING
EXAMPLES
SEE ALSO
KEYWORDS
ns_proxy provides a simple, robust proxy mechanism to evaluate
Tcl scripts in a separate, pipe-connected process. This approach
can be useful both to isolate potentially thread-unsafe code outside
the address space of a multithreaded process such as NaviServer or
to enable separation and timeout of potentially misbehaving, long
running scripts.
The command is provided by the nsproxy dynamic library which
can be loaded into an interpreter via the Tcl load command,
for example:
| |
load /usr/local/lib/libnsproxy.so
ns_proxy ...
|
It is also possible to load the library into all interpreters of
an NaviServer virtual server by specifying an nsproxy.so entry
in the server's module config entry, for example:
| |
ns_section ns/server/server1/modules
ns_param nsproxy nsproxy.so
|
When loaded, the library adds the single ns_proxy command with
takes multiple options as described below. Proxies (i.e. slave
processes) are normally created on demand when requested and connected
to the parent process via pipes used to send scripts and receive response.
Proxies remain active until the parent process exits, effectively closing
all pipes to the slave processes, or when their idle timer expires, depending
on the setup of the pool (see ns_proxy configure).
Proxies are obtained from their corresponding pool by means of the
ns_proxy get command. Only the thread that obtained the proxy can use
it to communicate with the slave process. In order to allow other threads to
use the same proxy, the thread must return (via the ns_proxy put or
ns_proxy cleanup commands) the proxy back to it's/theirs correspondig
pool/s. One thread can obtain one or a bunch of proxies from a pool in one step.
It cannot, however, repeatedly obtain proxy by proxy in a loop, as this may
lead to difficult-to-trace deadlock situation (see ns_proxy get command).
- ns_proxy pools
-
Returns a list of all currently defined proxy pools.
- ns_proxy handles
-
Returns list of all proxies allocated for the current interpreter.
- ns_proxy cleanup
-
Releases any handles from any pools currently owned by a thread.
This command is intended to be used as part of a garbage collection
step. Calling this command within NaviServer is not necessary as the
module registers a trace to release all handles via the
Ns_TclRegisterTrace facility when interpreters are deallocated
after some transaction, for example, at the end of a connection.
- ns_proxy active pool ?handle?
-
Returns a list of currently evaluating scripts in proxies for
the given pool. The output is one or more lists, depending on
the optional ?handle? argument. If the optional argument is
given, only the status of the proxy for the given handle is
returned and the result is a one-element list. Otherwise, stati of
all active proxies for the given pool are returned and the
result is a list of two or more elements.
Each element itself is a list which includes several keys: handle,
slave, start, script and their associated values.
This format is suitable for filling in an Tcl array with the
array set Tcl command.
The handle key contains the handle of the proxy.
The slave key contains the process-id of the slave process.
The start key contains the timestamp with the absolute time
when this proxy has been activated. The timestamp is in format that
ns_time command understands.
The script contains the script passed to the proxy for execution.
It is also possible to view the currently evaluating scripts with the
Unix ps command as the proxy slave process re-writes it's command
argument space with the request script before evaluation and clears it
after sending the result.
- ns_proxy free pool
-
Returns a list of all free proxies for the given pool. Free
proxies are those which are left in the pool queue waiting to
be used by the ns_proxy get command. Some proxies may have
an active slave process attached, some not. If a slave process is
not attached to the free proxy, a new one will be created as soon
as the proxy is requested by some thread.
- ns_proxy clear pool ?handle?
-
Stop all slave processes attached to free proxies for the given pool.
If the optional ?handle? is given, it stops the process only for
that handle.
- ns_proxy stop pool ?handle?
-
Stop all slave processes attached to running proxies for the given pool.
If the optional ?handle? is given, it stops the process only for
that handle.
- ns_proxy configure pool ?-key val -key val...?
-
Configures options for the pool. The pool is created with
default options if it does not already exist. Default options for the
pool are taken from the NaviServer configuration file under the
section "ns/server/$servername/module/nsproxy". In case
the library is loaded in plain Tcl shell, default configuration options
are fixed and cannot be changed w/o recompiling the code.
Configurable options include:
- -init script
-
Specifies a script to evaluate when proxies are started. This can
be used to load additional libraries and/or source script files.
The default is no script.
- -reinit script
-
Specifies a script to evaluate after being allocated and before
being returned to the caller. This can be used to re-initalize
the slave state. The default is no script.
- -maxslaves n
-
Sets the maximum number of proxy slave processes. Requests for
proxies beyond the maximum will result in requesting threads
waiting for existing proxies to be available instead of creating
new proxy processes. Setting this value to 0 disables the pool,
causing all subsequent allocation requests to fail immediately
(currently allocated proxies, if any, remain valid).
- -maxruns n
-
Sets the maximum number of activation of the proxy slave process.
When the limit it reached, the slave process is automatically restarted.
- -exec program
-
Specifies the filename of a slave proxy program. This defaults to
nsproxy in the bin subdirectory of the NaviServer
runtime. It is possible to create a custom program and enter the
proxy event loop with the Ns_ProxyMain application startup
routine; see the source code for details.
- -gettimeout ms
-
Specifies the maximum time to wait to allocate handles from the pool.
The default is 5000 milliseconds.
- -evaltimeout ms
-
Specifies the maximum time to wait for a script to be evaluated in
a proxy. This parameter can be overridden on a per-call basis with
the optional ?timeout? parameter to ns_proxy eval.
The default is 0 milliseconds i.e. infinite.
- -sendtimeout ms
-
- -recvtimeout ms
-
Specifies the maximium time to wait to send a script and receive a
result from a proxy. The default is 1000 milliseconds which assumes
minimal delay sending and receiving reasonably sized scripts and
results over the connecting pipe.
- -waittimeout ms
-
Specifies the maximum time to wait for a proxy to exit. The wait
is performed in a dedicated reaper thread. The reaper will close
the connection pipe and wait the given timeout. If the timeout is
exceeded, the reaper will send a SIGTERM signal and finally a SIGKILL
signal to ensure the process eventually exits. The default is 100
milliseconds which should be ample time for a graceful exit unless
the process is hung executing a very long, misbehaving script,
resulting in a more disruptive SIGTERM or SIGKILL.
- -idletimeout ms
-
Specifies the maximum time for an idle slave process to live.
Minimum value is 5000 milliseconds. After expiry of the idle
timeout, the reaper thread will close the connection pipe and
wait -waittimeout milliseconds for the process to die.
If the timeout is exceeded, the reaper will send a SIGTERM
signal and finally a SIGKILL signal (waiting -waittimeout
milliseconds in between) to ensure the process eventually exits.
Slave processes whose handles are already attached to some Tcl
interps by the means of the ns_proxy get command) are not
expired automatically. The idle timer starts to count at the moment
their handles are put back to the pool by the ns_proxy put
or ns_proxy cleanup command.
- ns_proxy get pool ?-handles n? ?-timeout ms?
-
Returns one or more handles to proxies from the specified pool.
The pool will be created with default options if it does not
already exist. The optional ?-handle n? arguments can be used
to specify the number of handles to allocate, the default being 1.
The optional ?-timeout ms? arguments specifies the maximum
amount of time in milliseconds to wait for the handles to become
available before raising an error (see ERROR HANDLING below
for details on handling errors). Requesting more than one handle in
a single call (if more than one handle is required) is necessary as it
is an error to request handles from a pool from which handles are
already owned by the thread. This restriction is implemented to avoid
possible deadlock conditions.
The handle returned by this command can be used as a scalar value for
other ns_proxy commands, or it can be used as Tcl command itself
(see ns_proxy eval for more information).
The proxy pool naming convention allows proxy slaves to be started
under different Unix UID/GID then the server itself. For that to work,
the server must be running under root user (UID = 0). The naming
convention is simple: pool_name:<optional_user_id>:<optional_group_id>.
For example, to start the proxy for the pool "mypool" with user UID
of 100 the pool name can be constructed as: "mypool:100". To start the
proxy with UID of 100 and group GID of 200: "mypool:100:200". Instead
of numeric values user/group names can also be used.
Beware: if the main server is not running under privileged root user,
the startup of the proxy under some alternative UID/GID may/will fail.
- ns_proxy ping handle
-
This command sends a null request to the proxy specified by the
handle argument. The proxy will be verified alive and restarted
if necessary. This command is not normally required as the
ns_proxy eval command will also verify and restart proxies
as needed.
- ns_proxy send handle script
-
Sends script to the proxy specified by handle.
(see ERROR HANDLING below for details on handling errors).
- ns_proxy wait handle ?timeout?
-
Waits for results from the proxy specified by handle.
The optional ?timeout? argument specifies a maximum number of
milliseconds to wait for the command to complete before raising an
error (see ERROR HANDLING below for details on handling errors).
- ns_proxy recv handle
-
Reads result from the script from the proxy specified by handle
(see ERROR HANDLING below for details on handling errors).
- ns_proxy eval handle script ?timeout?
-
Evalutes script in the proxy specified by handle.
The optional ?timeout? argument specifies a maximum number of
milliseconds to wait for the command to complete before raising an
error (see ERROR HANDLING below for details on handling errors).
Alternatively, the handle itself may be used as Tcl command like
in the example below:
| |
set handle [ns_proxy get mypool]
$handle "short_running_proc"
$handle "long_running_proc" 20000
|
- ns_proxy put handle
-
This command can be used to release a single proxy specified by the
handle argument. All handles owned by a thread to the
cooresponding pool must be returned before any handles can be
allocated again. Within NaviServer, a call to this routine is
recommended for clarity but not strictly necessary. NaviServer installs
a trace to release all handles at the end of every connection during
interpreter deallocation.
Errors generated by a script evaluated in a proxy interpreter are
completely returned to the calling interpreter, including mapping
the errorInfo and errorCode global variables from the
proxy to the parent and raising a Tcl exception. This enables proxy
code to look very similar to that which may use the Tcl eval
command.
Errors raised by a failure to communicate with the proxy process
due to a timeout or unexpected process exit are also communicated
back to the parent interpreter as Tcl exceptions. To distinguish
between these cases, communication related errors set the
errorCode global variable with the first element
NSPROXY. The second element is one of the following:
- EDeadlock
-
The interpreter attempted to allocate handles from a pool from which
it already owns one or more handles.
- EExec
-
The slave program specified by the -exec program option could
not be started.
- EImport
-
The response from the proxy was invalid.
- ERecv
-
There was an error receiving the result from the slave process.
- ESend
-
There was an error sending the script to the slave process.
- EGetTimeout
-
Timeout while waiting to get a proxy handle from the pool.
- EEvalTimeout
-
Timeout while waiting for the response from the proxy process after
sending the command for evaluation.
- ERange
-
Requested too many proxy handles from the pool
- EIdle
-
Proxy is currently in the idle state.
- EInit
-
Evaluation of the init script failed.
- EDead
-
Proxy handle is currently not connected to any process.
- EBusy
-
Proxy handle is currently busy with the evaluation.
The following demonstrates sending a script to a remote proxy:
| |
set handle [ns_proxy get myproxy]
ns_proxy eval $handle {info patchlevel}
ns_proxy release $handle
|
Alternatively, instead of using the scalar handle you can use
the handle directly as an Tcl command:
| |
set handle [ns_proxy get myproxy]
$handle {info patchlevel}
rename $handle ""
|
The following demonstrates using multiple proxies:
| |
ns_proxy config myproxy -maxslaves 10
set handles [ns_proxy get myproxy -handle 10]
foreach h $handles {
$h {puts "alive: [pid]"}
}
ns_proxy cleanup
|
nsd
NaviServer , ns_proxy