DragonFly On-Line Manual Pages
bgexec(n) BLT Built-In Commands bgexec(n)
______________________________________________________________________________
NAME
bgexec - Run programs in the background while handling Tk events. kill
- Terminate program or send signal.
SYNOPSIS
blt::bgexec varName ?switches? program ?arg?...
blt::kill processid ?signal?
______________________________________________________________________________
DESCRIPTION
The kill command terminates a processid or under unix sends a signal.
The bgexec command executes a program pipleline using the Tcl event-
loop allowing other events to continue to be serviced. Upon completion
it sets the global variable varName with a list of 4 status values: a
text token, the process-id, the exit code, and a text message. Bgexec
provides capabilities similar to the exec command, but with added
support for callbacks, output to variables and termination.
When used with no options, the returned value from bgexec is the output
from the program. But when the last arg is an ampersand (&) the
program runs detached, and bgexec immediately returns with a list of
the process ids created in the command pipeline. Detached processes
can be interrupted and terminated simply by setting varName.
The valid switches are as follows:
-check num
Interval in ms to poll for the exiting processes. The default
is 1000.
-closeonkill millisecs
Force close of stdin/stdout on kill after the given interval.
This lets kill finalize processes, even uninterruptably sleeping
ones unable to receive signals. The default is 0 for do not
force close.
-command script
Specifies a command to call upon command completion/termination.
Two extra arguments are appended before the call. The data
output from the command, and the status info as set into
varName.
-decodeerror encodingName
Specifies the encoding of the stderr channel. This affects only
data returned to the Tcl interpreter. No translation is done on
file redirection. For example if data is to be converted from
Unicode for use in Tcl, you would use the "unicode" encoding.
The default is that no tranlation is performed.
-decodeoutput encodingName
Specifies the encoding of the stdout channels. This affects
only data returned to the Tcl interpreter. No translation is
done on file redirection. For example if data is to be
converted from Unicode for use in Tcl, you would use the
"unicode" encoding. The default is that no tranlation is
performed.
-echo boolean
Indicates if the pipeline's stderr stream should be echoed.
Note: this option is deprecated.
-error varName
Specifies that a global variable varName is to be set with the
contents of stderr after the program has completed.
-keepnewline boolean
Specifies that a trailing newline should be retained in the
output. If boolean is true, the trailing newline is truncated
from the output of the -onoutput and -output variables. The
default value is true.
-killsignal signal
Specifies the signal to be sent to the program when terminating.
This option is available only on Unix. Signal can either be a
number (typically 1-32) or a mnemonic (such as SIGINT). If
signal is the empty string, then no signal is sent. The default
signal is 9 (SIGKILL).
-lasterror varName
Specifies a variable varName that is updated whenever data
becomes available from standard error of the program. VarName
is a global variable. Unlike the -error option, data is
available as soon as it arrives.
-lastoutput varName
Specifies a variable varName that is updated whenever data
becomes available from standard output of the program. VarName
is a global variable. Unlike the -output option, data is
available as soon as it arrives.
-limit numBytes
Limit the size of the returned data to numBytes, terminating the
program if exceeded. The limit applies to both stdout and
stderr.
-linebuffered boolean
Specifies that updates should be made on a line-by-line basis.
Normally when new data is available bgexec will set the variable
(-lastoutput and -lasterror options) or invoke the command
(-onoutput and -onerror options) delivering all the new data
currently available. If boolean is true, only one line at a
time will be delivered. This can be useful when you want to
process the output on a line-by-line basis. The default value
is false.
-local boolean
When boolean is true, any unqualified variables or command
options are treated as local to the current namespace. This is
mostly useful for non-detaching (no ampersand) commands. Note
that using this flag with a detached command will use variables
from the current namespace, not from the current proc stack-
frame.
-onerror command
Specifies the start of a Tcl command that will be executed
whenever new data is available from standard error. The data is
appended to the command as an extra argument before it is
executed.
-onoutput command
Specifies the start of a Tcl command that will be executed
whenever new data is available from standard output. The data is
appended to the command as an extra argument before it is
executed.
-output varName
Specifies a global variable varName to be set with the output of
the program, upon completion.
-raise boolean
When boolean is true, a non-zero return code from a non-detached
command will raise an error (.ie emulates exec). The default is
false an error is generated only if one of the following occurs:
invalid options are given, a redirection error, or process
creation failure (eg. executable program not found). Detached
commands, of course, never raise an error on a non-zero return
code.
-- This marks the end of the options. The following argument will
be considered the name of a program even if it starts with a
dash (-).
USAGE
Invoking bgexec without a trailing ampersand will block and wait for
result. However, other Tcl events continue to be serviced. This
prevents Tcl from hanging, eg:
pack [text .t]
set val [blt::bgexec myStatus du -s]
Note that text widget .t continues to respond to events.
CALLBACKS
Here is an example that invokes the Unix du program with a -command
callback.
proc Done {data status} { puts "Done($status)\n$data" }
blt::bgexec myStatus -command Done du -s $dir &
When du has completed, the handler Done is called with data and status.
Also, the global variable myStatus is set to contain the program's exit
status, eg:
EXITED 26811 0 {child completed normally}
If myStatus is set before du has completed, the process will be killed.
Under Unix, this sends a signal (SIGKILL by default). Under Win32,
TerminateProcess is called.
VARIABLE
Here is another example, this time using the -output option to direct
output to a variable.
global myStatus myOutput
blt::bgexec myStatus -output myOutput du -s $dir
puts "Disk usage for $dir is $myOutput"
Upon completion, MyOutput will contain the output of the program.
STDERR
Various bgexec options can be used to capture stderr separately from
stdout.
global myStatus myOutput myErrs
blt::bgexec myStatus -output myOutput -error myErrs du -s $dir
The -error option is similar to -output in that it sets a variable when
the program completes with data written to stderr.
LOCAL
By default, bgexec treats variable or command options as being in the
global namespace. The -local option can change this to use the current
namespace. Thus data can be collected to namespace-local variables
even those inside of procs, eg.
proc Work {} {
blt::bgexec myStatus -local 1 -output val -error err du -s
puts "VAL=$val"
puts "ERR=$err"
}
which collects data to local variables.
For detached processes, -local will cause data to aggregate to
namespace variables, ie. outside the proc, eg.
namespace eval ::Ns {
set pval {}
set perr {}
proc Work {} {
blt::bgexec myStatus -local 1 -output pval -error perr du -s &
}
}
This collects data to ::Ns::pval and stderr to ::Ns::perr. Similarly,
proc names (eg -onoutput) will be relative to the current namespace.
PROGRESS
The -output and -error variables are set only after the program
completes. But if a program runs for a long time, you can gather data
as it becomes available using the -onoutput option. As new data
becomes available, this command is executed, with data appended as an
argument.
proc GetInfo { data } { puts $data }
blt::bgexec myStatus -onoutput GetInfo du -s $dir
The -onerror option performs a similar function for the stderr data
stream.
ERROR HANDLING
Like exec, bgexec returns an error if the exit code of the program is
non-zero. To handle this invoke bgexec from within a catch.
catch { blt::bgexec myStatus -output myOutput du -s $dir }
Detached jobs will generate an error only if the program startup
failed. Otherwise the only indication is the status code set in
myStatus.
TKWAIT
By default, bgexec waits for a program to finish and returns the
resulting output. To detach a program simply append an ampersand (&)
as the last argument on the command line, eg.
global myStatus myOutput
blt::bgexec myStatus -output myOutput du -s $dir &
Bgexec will then return immediately with the spawned process ids as the
result. If needed tkwait can be used to wait for the program to
finish:
global myStatus myOutput
blt::bgexec myStatus -output myOutput du -s $dir &
...
tkwait variable myStatus
Note however that using tkwait can be dangerous. Multiple tkwait/vwait
calls must complete in the reverse order called. The BLT busy command
can be used to try and enforce this, but a better alternative is to
just use -command instead.
DIFFERENCES WITH EXEC
Using bgexec without an ampersand will not hang Tcl: events continue to
be serviced by the event handler while the call blocks. Also unlike
exec, an error will not be generated if output is appears on stderr.
And output from stderr can be separately managed and collected (without
having to redirect to files). Finally, bgexec ensures that invoked
processes get properly cleaned up at termination.
DIFFERENCES WITH FILEEVENT
Since Tk 4.0, a subset of bgexec can be achieved using the fileevent
command. The steps for running a program in the background are:
Execute the program with the open command (using the "|" syntax) and
save the file handle.
global fileId
set fileId [open "|du -s $dir" r]
Next register a Tcl code snippet with fileevent to be run whenever
output is available on the file handle. The code snippet will read
from the file handle and save the output in a variable.
fileevent fileId readable {
if { [gets $fileId line] < 0 } {
close $fileId
set output $temp
unset fileId temp
} else {
append temp $line
}
}
However, Bgexec is simpler and less error prone than using open +
fileevent. You don't have to worry about non-blocking I/O. Everything
is handled for you automatically.
Moreover, bgexec can run programs that fileevent can not. Fileevent
assumes that the when stdout is closed the program has completed. But
some programs, like the Unix compress program, reopen stdout, fooling
fileevent into thinking the program has terminated. In the example
above, we assume that the program will write and flush its output line-
by-line. However when running another program, your application can
block in the gets command reading a partial line.
Bgexec gives you get back the exit status of the program. It also lets
you reliably kill detached processes and allows you to collect data
from both stdout and stderr individually. Finally, since data
collection is handled in C code, bgexec is faster and more efficient.
SEE ALSO
busy, exec, tkwait, vwait
KEYWORDS
exec, background, busy
BLT 2.5 bgexec(n)