Programming with AOLserver
by Michael Yoon and Jon Salz
part of the ACS Engineering Manual
The global
command
When using AOLserver, remember that there are effectively two
types of global namespace, not one:
- Server-global: As you'd expect, there is
only one server-global namespace per server, and variables set within
it can be accessed by any Tcl code running subsequently, in any of the
server's threads. To set/get server-global variables, use AOLserver
3's
nsv
API (which supersedes ns_share
from the pre-3.0 API).
- Script-global: Each Tcl script (ADP, Tcl
page, registered proc, filter, etc.) executing within an AOLserver
thread has its own global namespace. Any variable set in the top level
of a script is, by definition, script-global, meaning that it is
accessible only by subsequent code in the same script and only for the
duration of the current script execution.
The Tcl built-in command global
accesses script-global, not server-global, variables from
within a procedure. This distinction is important to understand in
order to use global
correctly when programming AOLserver.
Also, AOLserver purges all script-global variables in a thread (i.e.,
Tcl interpreter) between HTTP requests. If it didn't, that would
affect (and complicate) our use of script-global variables
dramatically, which would then be better described as
thread-global variables. Given AOLserver's behaviour,
however, "script-global" is a more appropriate term.
Threads and Scheduled Procedures
ns_schedule_proc
and ad_schedule_proc
each take
a -thread
flag to cause a scheduled procedure to run
asychronously, in its own thread. It almost always seems like a good idea
to specify this switch, but there's a problem.
It turns out that whenever a task scheduled with
ns_schedule_proc -thread
or ad_schedule_proc -thread t
is run, AOLserver creates a brand new thread and a brand new
interpreter, and reinitializes the procedure table
(essentially, loads all procedures that were
created during server initialization into the new interpreter). This happens
every time the task is executed - and it
is a very expensive process that should not be taken lightly!
The moral: if you have a lightweight scheduled procedure which runs
frequently, don't use the -thread
switch.
Using return
The return command in TCL returns control to the caller
procedure. This definition allows nested procedures to work
properly. However, this definition also means that nested procedures
cannot use return to end an entire thread. This situation is
most common in exception conditions that can be triggered from inside
a procedure e.g., a permission denied exception. At this point, the
procedure that detects invalid permission wants to write an error
message to the user, and completely abort execution of the caller
thread. return doesn't work, because the procedure may be
nested several levels deep. We therefore use ad_script_abort
to abort the remainder of the thread. Note that using return
instead of ad_script_abort may raise some security issues: an
attacker could call a page that performed some DML statement, pass
in some arguments, and get a permission denied error -- but the DML
statement would still be executed because the thread was not
stopped. Note that return -code return can be used in
circumstances where the procedure will only be called from two levels
deep.
michael@arsdigita.com
jsalz@mit.edu