'\" '\" Copyright 1991-1997 by Bell Labs Innovations for Lucent Technologies. '\" '\" Permission to use, copy, modify, and distribute this software and its '\" documentation for any purpose and without fee is hereby granted, provided '\" that the above copyright notice appear in all copies and that both that the '\" copyright notice and warranty disclaimer appear in supporting documentation, '\" and that the names of Lucent Technologies any of their entities not be used '\" in advertising or publicity pertaining to distribution of the software '\" without specific, written prior permission. '\" '\" Lucent Technologies disclaims all warranties with regard to this software, '\" including all implied warranties of merchantability and fitness. In no event '\" shall Lucent Technologies be liable for any special, indirect or '\" consequential damages or any damages whatsoever resulting from loss of use, '\" data or profits, whether in an action of contract, negligence or other '\" tortuous action, arising out of or in connection with the use or performance '\" of this software. '\" '\" Bgexec command created by George Howlett. '\" '\" The definitions below are for supplemental macros used in Tcl/Tk '\" manual entries. '\" '\" .AP type name in/out ?indent? '\" Start paragraph describing an argument to a library procedure. '\" type is type of argument (int, etc.), in/out is either "in", "out", '\" or "in/out" to describe whether procedure reads or modifies arg, '\" and indent is equivalent to second arg of .IP (shouldn't ever be '\" needed; use .AS below instead) '\" '\" .AS ?type? ?name? '\" Give maximum sizes of arguments for setting tab stops. Type and '\" name are examples of largest possible arguments that will be passed '\" to .AP later. If args are omitted, default tab stops are used. '\" '\" .BS '\" Start box enclosure. From here until next .BE, everything will be '\" enclosed in one large box. '\" '\" .BE '\" End of box enclosure. '\" '\" .CS '\" Begin code excerpt. '\" '\" .CE '\" End code excerpt. '\" '\" .VS ?version? ?br? '\" Begin vertical sidebar, for use in marking newly-changed parts '\" of man pages. The first argument is ignored and used for recording '\" the version when the .VS was added, so that the sidebars can be '\" found and removed when they reach a certain age. If another argument '\" is present, then a line break is forced before starting the sidebar. '\" '\" .VE '\" End of vertical sidebar. '\" '\" .DS '\" Begin an indented unfilled display. '\" '\" .DE '\" End of indented unfilled display. '\" '\" .SO '\" Start of list of standard options for a Tk widget. The '\" options follow on successive lines, in four columns separated '\" by tabs. '\" '\" .SE '\" End of list of standard options for a Tk widget. '\" '\" .OP cmdName dbName dbClass '\" Start of description of a specific option. cmdName gives the '\" option's name as specified in the class command, dbName gives '\" the option's name in the option database, and dbClass gives '\" the option's class in the option database. '\" '\" .UL arg1 arg2 '\" Print arg1 underlined, then print arg2 normally. '\" '\" RCS: @(#) $Id: man.macros,v 1.3 2001/02/17 07:46:19 ghowlett Exp $ '\" '\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b '\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. '\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out '\" # BS - start boxed text '\" # ^y = starting y location '\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. '\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. '\" # VS - start vertical sidebar '\" # ^Y = starting y location '\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. '\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. '\" # Special macro to handle page bottom: finish off current '\" # box/sidebar if in box/sidebar mode, then invoked standard '\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. '\" # DS - begin display .de DS .RS .nf .sp .. '\" # DE - end display .de DE .fi .RE .sp .. '\" # SO - start of list of standard options .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 4c 8c 12c .ft B .. '\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. '\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. '\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .ft CW .sp .. '\" # CE - end code excerpt .de CE .fi .RE .ft R .sp .. .de UL \\$1\l'|0\(ul'\\$2 .. .TH bgexec n 2.4 BLT "BLT Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME bgexec \- Run programs in the background while handling Tk events. .SH SYNOPSIS \fBblt::bgexec \fIvarName\fR ?\fIoption value\fR?... \fIprogram\fR ?\fIarg\fR?... .BE .SH DESCRIPTION .PP The \fBbgexec\fR command executes programs in the background, allowing Tk to handle events. A global Tcl variable \fIvarName\fR is set when the program has completed. .SH INTRODUCTION Tcl's \fBexec\fR command is very useful for gathering information from the operating system. It runs a program and returns the output as its result. This works well for Tcl-only applications. But for Tk applications, a problem occurs when the program takes time to process. Let's say we want the get the disk usage of a directory. We'll use the Unix program \f(CWdu\fR to get the summary. .CS set out [exec du -s $dir] puts "Disk usage for $dir is $out" .CE While \f(CWdu\fR is running, scrollbars won't respond. None of the Tk widgets will be redrawn properly. The \fBsend\fR command won't work. And the worst part is that the application appears hung up or dead. The problem is that while \fBexec\fR is waiting for \fIdu\fR to finish, Tk is not able to handle X events. .PP The \fBbgexec\fR command performs the same functions as \fBexec\fR, but also allows Tk to handle events. You can execute a long-running program and the Tk widgets will behave normally. When the program finishes, its output and the exit status are written to Tcl variables. This makes it easy to monitor and save the output of a program. .SH EXAMPLE Here is the disk usage example again, this time using \fBbgexec\fR. The syntax to invoke "du" is exactly the same as the previous example, when we used \fBexec\fR. .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir puts "Disk usage for $dir is $myOutput" .CE Two global variables, \f(CWmyStatus\fR and \f(CWmyOutput\fR, will be set by \fBbgexec\fR when \f(CWdu\fR has completed. \f(CWMyStatus\fR will contain the program's exit status. \f(CWMyOutput\fR, specified by the \fB\-output\fR option, will store the output of the program. .PP You can also terminate the program by setting the variable \f(CWmyStatus\fR. If \f(CWmyStatus\fR is set before \f(CWdu\fR has completed, the process is killed. Under Unix, this is done sending by a configurable signal (by default it's SIGKILL). Under Win32, this is done by calling \fBTerminateProcess\fR. It makes no difference what \f(CWmyStatus\fR is set to. .CS set myStatus {} .CE There are several \fBbgexec\fR options to collect different types of information. .CS global myStatus myOutput myErrs blt::bgexec myStatus -output myOutput -error myErrs du -s $dir .CE The \fB\-error\fR option is similar to \fB\-output\fR. It sets a global variable when the program completes. The variable will contain any data written to stderr by the program. .PP The \fB\-output\fR and \fB\-error\fR variables are set only after the program completes. But if the program takes a long time, to run you may want to receive its partial output. You can gather data as it becomes available using the \fB\-onoutput\fR option. It specifies a Tcl command prefix. Whenever new data is available, this command is executed, with the data appended as an argument to the command. .CS proc GetInfo { data } { puts $data } blt::bgexec myStatus -onoutput GetInfo du -s $dir .CE When output is available, the procedure \f(CWGetInfo\fR is called. The \fB\-onerror\fR option performs a similar function for the stderr data stream. .PP Like \fBexec\fR, \fBbgexec\fR returns an error if the exit code of the program is not zero. If you think you may get a non-zero exit code, you might want to invoke \fBbgexec\fR from within a \fBcatch\fR. .CS catch { blt::bgexec myStatus -output myOutput du -s $dir } .CE By default, \fBbgexec\fR will wait for the program to finish. But you can detach the program making ampersand (&) the last argument on the command line. .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir & .CE \fBBgexec\fR will return immediately and its result will be a list of the spawned process ids. If at some point you need to wait for the program to finish up, you can use \fBtkwait\fR. When the program finishes, the variable \f(CWmyStatus\fR will be written to, breaking out the \fBtkwait\fR command. .CS global myStatus myOutput blt::bgexec myStatus -output myOutput du -s $dir & ... tkwait variable myStatus .CE .SH SYNTAX The \fBbgexec\fR command takes the following form: .sp \fB blt::bgexec \fIvarName\fR ?\fIoption value\fR?... \fIprogram\fR ?\fIarg\fR?... .sp \fIVarName\fR is the name of a global variable which is set when \fIprogram\fR has finished executing. The exit status of will be stored in \fIvarName\fR. The exit status is a list of a status token, the process-id of the program, the exit code, and a status message. You can also prematurely terminate the program by setting \fIvarName\fR. Under Unix, the program will be sent a signal to terminate it (by default the signal is a SIGKILL; see the \fB\-killsignal\fR option). .PP \fIProgram\fR is the name of the program to be executed and \fIargs\fR are any extra arguments for \fIprogram\fR. The syntax of \fIprogram\fR and \fIargs\fR is the same as the \fBexec\fR command. So you can redirect I/O, execute pipelines, etc. (see the \fBexec\fR manual for further information) just like \fBexec\fR. If the last argument is an ampersand (&), the program will be run detached, and \fBbgexec\fR will return immediately. \fIVarName\fR will still be set with the return status when \fIprogram\fR completes. .SH OPTIONS \fIOption\fR refers to the switch name always beginning with a dash (\-). \fIValue\fR is the value of the option. Option-value pairs are terminated either by the program name, or double dashes (\-\-). The following options are available for \fBbgexec\fR: .TP \fB\-decodeerror \fIencodingName\fR .br Specifies the encoding of the stderr channel. This affects only data returned to the Tcl interpreter. No translation is done on file redirection. .br 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 translation is performed. .TP \fB\-decodeoutput \fIencodingName\fR .br Specifies the encoding of the stdout channels. This affects only data returned to the Tcl interpreter. No translation is done on file redirection. .br 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 translation is performed. .TP \fB\-error \fIvarName\fR .br Specifies that a global variable \fIvarName\fR is to be set with the contents of stderr after the program has completed. .TP \fB\-keepnewline \fIboolean\fR Specifies that a trailing newline should be retained in the output. If \fIboolean\fR is true, the trailing newline is truncated from the output of the \fB\-onoutput\fR and \fB\-output\fR variables. The default value is \f(CWtrue\fR. .TP \fB\-killsignal \fIsignal\fR Specifies the signal to be sent to the program when terminating. This is available only under Unix. \fISignal\fR can either be a number (typically 1-32) or a mnemonic (such as SIGINT). If \fIsignal\fR is the empty string, then no signal is sent. The default signal is \f(CW9\fR (SIGKILL). .TP \fB\-lasterror \fIvarName\fR Specifies a variable \fIvarName\fR that is updated whenever data becomes available from standard error of the program. \fIVarName\fR is a global variable. Unlike the \fB\-error\fR option, data is available as soon as it arrives. .TP \fB\-lastoutput \fIvarName\fR Specifies a variable \fIvarName\fR that is updated whenever data becomes available from standard output of the program. \fIVarName\fR is a global variable. Unlike the \fB\-output\fR option, data is available as soon as it arrives. .TP \fB\-linebuffered \fIboolean\fR Specifies that updates should be made on a line-by-line basis. Normally when new data is available \fBbgexec\fR will set the variable (\fB\-lastoutput\fR and \fB\-lasterror\fR options) or invoke the command (\fB\-onoutput\fR and \fB\-onerror\fR options) delivering all the new data currently available. If \fIboolean\fR 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 \f(CWfalse\fR. .TP \fB\-output \fIvarName\fR .br Specifies that a global variable \fIvarName\fR is to be set with the output of the program, once it has completed. If this option is not set, no output will be accumulated. .TP \fB\-onerror \fIcommand\fR 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. .TP \fB\-onoutput \fIcommand\fR 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. .TP \fB\-update \fIvarName\fR Deprecated. This option is replaced by \fB\-lasterror\fR. .TP \fB\-\|\-\fR 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 (\fB\-\fR). .SH PREEMPTION Because \fBbgexec\fR allows Tk to handle events while a program is running, it's possible for an application to preempt itself with further user-interactions. Let's say your application has a button that runs the disk usage example. And while the \f(CWdu\fR program is running, the user accidently presses the button again. A second \fBbgexec\fR program will preempt the first. What this means is that the first program can not finish until the second program has completed. .PP Care must be taken to prevent an application from preempting itself by blocking further user-interactions (such as button clicks). The BLT \fBbusy\fR command is very useful for just these situations. See the \fBbusy\fR manual for details. .SH DIFFERENCES WITH FILEEVENT Since Tk 4.0, a subset of \fBbgexec\fR can be also achieved using the \fBfileevent\fR command. The steps for running a program in the background are: .PP Execute the program with the \fBopen\fR command (using the "|" syntax) and save the file handle. .CS global fileId set fileId [open "|du -s $dir" r] .CE Next register a Tcl code snippet with \fBfileevent\fR 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. .CS fileevent fileId readable { if { [gets $fileId line] < 0 } { close $fileId set output $temp unset fileId temp } else { append temp $line } } .CE .PP The biggest advantage of \fBbgexec\fR is that, unlike \fBfileevent\fR, it requires no additional Tcl code to run a program. It's simpler and less error prone. You don't have to worry about non-blocking I/O. It's handled transparently for you. .PP \fBBgexec\fR runs programs that \fBfileevent\fR can not. \fBFileevent\fR assumes that the when stdout is closed the program has completed. But some programs, like the Unix \f(CWcompress\fR program, reopen stdout, fooling \fBfileevent\fR 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 running another program, your application may block in the \fBgets\fR command reading a partial line. .PP \fBBgexec\fR lets you get back the exit status of the program. It also allows you to collect data from both stdout and stderr simultaneously. Finally, since data collection is handled in C code, \fBbgexec\fR is faster. You get back to the Tk event loop more quickly, making your application seem more responsive. .SH SEE ALSO busy, exec, tkwait .SH KEYWORDS exec, background, busy