<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Wed May 22 21:59:29 GMT 2013 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='240'>
<header><title>An Ensemble Command to Manage Processes</title><author address="mailto:stevebold@hotmail.com">Steve Bold</author><status type='project' state='draft' tclversion="8.7" vote='prior'>$Revision: 1.14 $</status><history></history><created day='22' month='feb' year='2005' /><keyword>Tcl</keyword><obsoletes tip='88'/></header>
<abstract>This TIP proposes some new commands through which Tcl scripts can create and monitor child processes.</abstract>
<body><section title="Rationale">
<para>This TIP is intended to overcome the following limitations of the existing <emph style="bold">exec</emph> and <emph style="bold">open</emph> commands:</para>
<enumerate><item.e index='1'><para>While the stderr stream of a child process can be redirected to a file, it cannot be directed to a pipe and so cannot be captured progressively as the process runs. <tipref type="text" tip="202"/> has partially addressed this issue but only for the case where the child&apos;s stderr stream is directed to the same pipe as its stdout stream. Independent progressive capture of both stdout and stderr is still not possible.</para></item.e><item.e index='2'><para>In the (admittedly rare) case that a program has a significant delay between closing its standard streams and the process itself terminating, a Tcl script running that program as a background process cannot determine the exit status without blocking until the process terminates.</para></item.e><item.e index='3'><para>The existing <emph style="bold">exec</emph> and <emph style="bold">open</emph> commands impose a special interpretation on the characters <emph style="italic">&lt;&gt;|&amp;</emph>. This causes two kinds of problems:</para><itemize><item.i><para>scripts wishing to invoke a command on a remote computer using an <emph style="italic">rsh</emph> or similar command will sometimes wish to have characters such as <emph style="italic">&lt;&gt;|&amp;</emph> interpreted on the remote machine</para></item.i><item.i><para>scripts may pass a user entered string as an argument to exec. Such scripts may break unexpectedly if the comment string contains one of the special characters. Such problems could be considered a security weakness in Tcl.</para></item.i></itemize></item.e><item.e index='4'><para>Multiple child processes can be launched together with pipes used to link the streams of adjacent processes. However, little flexibility is provided in such cases, for example you can only capture the exit status of the last process in the pipeline.</para></item.e></enumerate>
<para>A more general problem is that each process related command is a separate top-level command. This is inconsistent with much else in Tcl, makes it harder to find the related commands in some forms of documentation and increases the risk of name clashes as new process related commands are introduced.</para>
<para>The BLT toolkit contains the command <emph style="bold">bgexec</emph> which addresses items (1) and (2) in the above list. However, the resulting implementation is complex and does not appear easy to transfer to the Tcl core. In addition, it is not clear to the author how <emph style="bold">bgexec</emph> could be extended to address items (3) and (4).</para>
<para>A variety of other approaches to addressing these problems are listed on the Wiki [<url ref="http://wiki.tcl.tk/1353"/>]. This suggests that it may be difficult to achieve a consensus on what the ideal command(s) for launching processes should look like. This TIP provides a basis through which many of these approaches could be implemented in pure Tcl. The commands specified in this TIP map easily onto the existing low level process related functions in the Tcl core, so the implementation cost is low.</para>
</section>
<section title="Specification">
<para>There shall be a new ensemble command, <emph style="bold">process</emph>, with at least four subcommands.</para>
<enumerate><item.e index='1'><para>The sub-command <emph style="bold">invoke</emph> takes 4 arguments and invokes a sub-process, returning the process id of the child process. The arguments are (in order):</para><itemize><item.i><para>a list containing the program name invoke and its arguments</para></item.i><item.i><para>a channel to be connected to the stdin stream of the child process (or an empty string if the channel is to be disconnected in the child process).</para></item.i><item.i><para>a channel to be connected to the stdout stream of the child process (or an empty string if the channel is to be disconnected in the child process).</para></item.i><item.i><para>a channel to be connected to the stderr stream of the child process (or an empty string if the channel is to be disconnected in the child process).</para></item.i></itemize></item.e><item.e index='2'><para>The sub-command <emph style="bold">pipe</emph> takes no arguments and returns a two element list containing the input and output channels of the pipe in that order.</para></item.e><item.e index='3'><para>The sub-command <emph style="bold">status</emph> takes a single argument which is a process id and returns a two element list. The first element is either <emph style="italic">running</emph> or <emph style="italic">completed</emph> The second element is the exit status of the process.</para><para>A process will report an arbitrary exit status of zero while it is running.</para></item.e><item.e index='4'><para>The sub-command <emph style="bold">wait</emph> is similar to <emph style="bold">status</emph> but blocks until the child process has completed.</para></item.e></enumerate>
</section>
<section title="Examples">
<para>The following shows how the commands proposed here can be used to produce a <emph style="bold">bgexec</emph> like command in pure Tcl. Not all the <emph style="bold">bgexec</emph> options are included and the implementation lacks the error handling needed for a robust implementation.</para>
<verbatim><vline encoding='base64'>cHJvYyBiZ0V4ZWNDbG9zZUhhbmRsZXIge3BpZCBjbWR9IHs=</vline><vline encoding='base64'>ICAgbGFzc2lnbiBbcHJvY2VzcyBzdGF0dXMgJHBpZF0gc3RhdHVzIGV4aXRDb2Rl</vline><vline encoding='base64'>ICAgaWYgeyRzdGF0dXMgZXEgInJ1bm5pbmcifSB7</vline><vline encoding='base64'>ICAgICAgcHV0cyAiLi4uIGRlZmVycmluZyBjbG9zZSBoYW5kbGluZyBmb3IgJHBpZCI=</vline><vline encoding='base64'>ICAgICAgYWZ0ZXIgMTAwMCBbbGlzdCBiZ0V4ZWNDbG9zZUhhbmRsZXIgJHBpZCAkY21kXQ==</vline><vline encoding='base64'>ICAgfSBlbHNlIHs=</vline><vline encoding='base64'>ICAgICAgaWYgeyRjbWQgbmUgIiJ9IHs=</vline><vline encoding='base64'>ICAgICAgICAge2V4cGFuZH0kY21kICRwaWQgJGV4aXRDb2Rl</vline><vline encoding='base64'>ICAgICAgfQ==</vline><vline encoding='base64'>ICAgfQ==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>cHJvYyBiZ0V4ZWNSZWFkSGFuZGxlciB7Y2hhbiBjbWR9IHs=</vline><vline encoding='base64'>ICAgaWYge1tnZXRzICRjaGFuIGxpbmVdID09IC0xfSB7</vline><vline encoding='base64'>ICAgICAgY2xvc2UgJGNoYW4=</vline><vline encoding='base64'>ICAgICAg</vline><vline encoding='base64'>ICAgICAgaWYge1tpbmZvIGV4aXN0cyA6OmJnRXhlY0Nsb3NlSW5mbygkY2hhbildfSB7</vline><vline encoding='base64'>ICAgICAgICAgbGFzc2lnbiAkOjpiZ0V4ZWNDbG9zZUluZm8oJGNoYW4pIHBpZCBjbWQ=</vline><vline encoding='base64'>ICAgICAgICAgYWZ0ZXIgMCBiZ0V4ZWNDbG9zZUhhbmRsZXIgJHBpZCAkY21k</vline><vline encoding='base64'>ICAgICAgICAgdW5zZXQgOjpiZ0V4ZWNDbG9zZUluZm8oJGNoYW4p</vline><vline encoding='base64'>ICAgICAgfQ==</vline><vline encoding='base64'>ICAgfSBlbHNlIHs=</vline><vline encoding='base64'>ICAgICAge2V4cGFuZH0kY21kICRsaW5l</vline><vline encoding='base64'>ICAgfQ==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>cHJvYyBiZ0V4ZWNMaWtlIHthcmdzfSB7</vline><vline encoding='base64'>ICAgc2V0IG91dENoYW4gIiI7IHNldCBlcnJDaGFuICIi</vline><vline encoding='base64'>ICAgc2V0IGkgMA==</vline><vline encoding='base64'>ICAgc2V0IGV4aXRDbWQgIiI7IHNldCBwYXJlbnRPdXRDaGFuICIi</vline><vline encoding='base64'>ICAgd2hpbGUgeyRpICE9IFtsbGVuZ3RoICRhcmdzXX0gew==</vline><vline encoding='base64'>ICAgICAgc2V0IGFyZyBbbGluZGV4ICRhcmdzICRpXQ==</vline><vline encoding='base64'>ICAgICAgc3dpdGNoIC1nbG9iIC0tICRhcmcgew==</vline><vline encoding='base64'>ICAgICAgCQ==</vline><vline encoding='base64'>ICAgICAgCS1vbm91dHB1dCB7</vline><vline encoding='base64'>ICAgICAgCSAgIGluY3IgaQ==</vline><vline encoding='base64'>ICAgICAgCSAgIHNldCBjbWQgW2xpbmRleCAkYXJncyAkaV0=</vline><vline encoding='base64'>ICAgICAgCSAgIGxhc3NpZ24gW3Byb2Nlc3MgcGlwZV0gcGFyZW50Q2hhbiBvdXRDaGFu</vline><vline encoding='base64'>ICAgICAgCSAgIGZpbGVldmVudCAkcGFyZW50Q2hhbiByZWFkYWJsZSBbbGlzdCBc</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgYmdFeGVjUmVhZEhhbmRsZXIgJHBhcmVudENoYW4gJGNtZF0=</vline><vline encoding='base64'>ICAgICAgCSAgIHNldCBvdXRDbWQgJGNtZA==</vline><vline encoding='base64'>ICAgICAgCSAgIHNldCBwYXJlbnRPdXRDaGFuICRwYXJlbnRDaGFu</vline><vline encoding='base64'>ICAgICAgCX0=</vline><vline encoding='base64'>ICAgICAgCQ==</vline><vline encoding='base64'>ICAgICAgCS1vbmVycm9yIHs=</vline><vline encoding='base64'>ICAgICAgCSAgIGluY3IgaQ==</vline><vline encoding='base64'>ICAgICAgCSAgIHNldCBjbWQgW2xpbmRleCAkYXJncyAkaV0=</vline><vline encoding='base64'>ICAgICAgCSAgIGxhc3NpZ24gW3Byb2Nlc3MgcGlwZV0gcGFyZW50Q2hhbiBlcnJDaGFu</vline><vline encoding='base64'>ICAgICAgCSAgIGZpbGVldmVudCAkcGFyZW50Q2hhbiByZWFkYWJsZSBbbGlzdCBc</vline><vline encoding='base64'>ICAgICAgICAgICAgICAgICAgYmdFeGVjUmVhZEhhbmRsZXIgJHBhcmVudENoYW4gJGNtZF0=</vline><vline encoding='base64'>ICAgICAgCX0=</vline><vline encoding='base64'>ICAgICAgCQ==</vline><vline encoding='base64'>ICAgICAgCS1vbmV4aXQgew==</vline><vline encoding='base64'>ICAgICAgCSAgIGluY3IgaQ==</vline><vline encoding='base64'>ICAgICAgCSAgIHNldCBleGl0Q21kIFtsaW5kZXggJGFyZ3MgJGld</vline><vline encoding='base64'>ICAgICAgCX0=</vline><vline encoding='base64'>ICAgICAgCQ==</vline><vline encoding='base64'>ICAgICAgCS0qIHs=</vline><vline encoding='base64'>ICAgICAgCSAgIGVycm9yICJVbmtub3duIHN3aXRjaCAkYXJnIg==</vline><vline encoding='base64'>ICAgICAgCX0=</vline><vline encoding='base64'>ICAgICAgCQ==</vline><vline encoding='base64'>ICAgICAgCSogew==</vline><vline encoding='base64'>ICAgICAgCSAgIGJyZWFr</vline><vline encoding='base64'>ICAgICAgCX0=</vline><vline encoding='base64'>ICAgICAgfQ==</vline><vline encoding='base64'>ICAgICAgaW5jciBp</vline><vline encoding='base64'>ICAgfQ==</vline><vline encoding='base64'>ICAg</vline><vline encoding='base64'>ICAgc2V0IGNtZExpbmUgW2xyYW5nZSAkYXJncyAkaSBlbmRd</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgIyBwdXRzIFtsaXN0IHByb2Nlc3MgaW52b2tlICRjbWRMaW5lICIiICRvdXRDaGFuICRlcnJDaGFuXQ==</vline><vline encoding='base64'>ICAgc2V0IHBpZCBbcHJvY2VzcyBpbnZva2UgJGNtZExpbmUgIiIgJG91dENoYW4gJGVyckNoYW5d</vline><vline encoding='base64'></vline><vline encoding='base64'>ICAgIyBDbG9zZSB0aGUgY2hpbGQgZW5kIG9mIHRoZSBwaXBlcyAtIGlmIHdlIG9wZW5lZCB0aGVtLg==</vline><vline encoding='base64'>ICAgZm9yZWFjaCB2YXIge291dENoYW4gZXJyQ2hhbn0gew==</vline><vline encoding='base64'>ICAgICAgaWYge1tzZXQgJHZhcl0gbmUgIiJ9IHs=</vline><vline encoding='base64'>ICAgICAgICAgY2xvc2UgW3NldCAkdmFyXQ==</vline><vline encoding='base64'>ICAgICAgfQ==</vline><vline encoding='base64'>ICAgfQ==</vline><vline encoding='base64'>ICAg</vline><vline encoding='base64'>ICAgaWYgeyRwYXJlbnRPdXRDaGFuIGVxICIifSB7</vline><vline encoding='base64'>ICAgICAgIyBQb2xsIGZvciBjaGlsZCBwcm9jZXNzIGV4aXQgdGhlbiBub3RpZnkgY2xpZW50LCBvciBhdCBsZWFzdA==</vline><vline encoding='base64'>ICAgICAgIyBjbGVhbiB1cCB0aGUgem9tYmllLg==</vline><vline encoding='base64'>ICAgICAgYWZ0ZXIgMCBiZ0V4ZWNDbG9zZUhhbmRsZXIgJHBpZCAkZXhpdENtZA==</vline><vline encoding='base64'>ICAgfSBlbHNlIHs=</vline><vline encoding='base64'>ICAgICAgIyBXZSBjb3B5IEJMVCdzIHRyaWNrIG9mIGRlZmVycmluZyBwb2xsaW5nIHRpbGwgdGhlIHN0ZG91dCBwaXBl</vline><vline encoding='base64'>ICAgICAgIyBjbG9zZXMuIFRoaXMgaXMgbWFyZ2luYWxseSBtb3JlIGVmZmljaWVudCwgbW9yZSBpbXBvcnRhbnRseQ==</vline><vline encoding='base64'>ICAgICAgIyBpdCBzdG9wcyBjbGllbnRzIGJlaW5nIG5vdGlmaWVkIG9mIHRoZWlyIHByb2Nlc3MgdW50aWwgYXQgc3Rkb3V0</vline><vline encoding='base64'>ICAgICAgIyBjaGFubmVsIGhhcyBjbG9zZWQu</vline><vline encoding='base64'>ICAgICAgc2V0IDo6YmdFeGVjQ2xvc2VJbmZvKCRwYXJlbnRPdXRDaGFuKSBbbGlzdCAkcGlkICRleGl0Q21kXQ==</vline><vline encoding='base64'>ICAgfSAgIA==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'></vline><vline encoding='base64'>IyBub3cgc2hvdyBiZ0V4ZWNMaWtlIGluIGFjdGlvbiAuLi4=</vline><vline encoding='base64'></vline><vline encoding='base64'>cHJvYyBzaG93RXhpdCB7cGlkIGNvZGV9IHs=</vline><vline encoding='base64'>ICAgcHV0cyAiJHBpZCB0ZXJtaW5hdGVkIHdpdGggY29kZSAkY29kZSI=</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>cHJvYyBzaG93TGluZSB7Y2hhbm5lbCBsaW5lfSB7</vline><vline encoding='base64'>ICAgcHV0cyAiJGNoYW5uZWw6ICRsaW5lIg==</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>cHJvYyBydW5McyB7YXJnc30gew==</vline><vline encoding='base64'>ICAgcHV0cyAiaW52b2tpbmcgbHMgb24gJGFyZ3Mi</vline><vline encoding='base64'>ICAgYmdFeGVjTGlrZSAtb25vdXRwdXQgInNob3dMaW5lIHN0ZG91dCIgLW9uZXJyb3IgInNob3dMaW5lIHN0ZGVyciIgXA==</vline><vline encoding='base64'>ICAgICAgICAgICAtb25leGl0IHNob3dFeGl0IGxzIHtleHBhbmR9JGFyZ3M=</vline><vline encoding='base64'>fQ==</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBTYW1wbGUgaW52b2NhdGlvbnM6IG5vdGUgd2hlbiBydW5uaW5nIHVuZGVyIHRjbHNoLCB0aGVyZSBpcyBubyBldmVudCBsb29wLA==</vline><vline encoding='base64'>IyB1c2UgJ3VwZGF0ZScgdG8gc2VlIHRoZSBvdXRwdXQgdG8gc2VlIHdoYXQncyBoYXBwZW5pbmcu</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBzdWNjZXNzZnVsIGxpc3Rpbmc=</vline><vline encoding='base64'>cnVuTHMgLg==</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBVbnN1Y2Nlc3NmdWwgbGlzdGluZw==</vline><vline encoding='base64'>cnVuTHMgbm90LWZvdW5k</vline><vline encoding='base64'></vline><vline encoding='base64'>IyBMaXN0aW5nIG9mIChub24gZXhpc3RlbnQpIGZpbGVzIGNvbnRhaW5pbmcgZXhlYy9vcGVuIG1ldGEgY2hhcmFjdGVycw==</vline><vline encoding='base64'>cnVuTHMgPCA+IHwgJg==</vline></verbatim>
</section>
<section title="Limitations">
<enumerate><item.e index='1'><para>For convenient use, the functionality proposed here needs to be supplemented with additional commands providing a higher level interface, perhaps one of them being similar to the <emph style="bold">bgExecLike</emph> example given previously. The author has decided to omit this feature from the TIP because:</para><itemize><item.i><para>such commands can be implemented in pure Tcl using the commands described here</para></item.i><item.i><para>the exact nature of the high level commands may produce lengthy discussions</para></item.i><item.i><para>it could even be argued that such commands are more appropriate in tcllib rather than the Tcl core</para></item.i></itemize></item.e><item.e index='2'><para>As with the current implementation of <emph style="bold">exec</emph>, each channel passed to <emph style="bold">process invoke</emph> must have a valid underlying OS file handle. Consequently when running on Windows:</para><itemize><item.i><para>use of a wish standard channel will be immediately rejected</para></item.i><item.i><para>use of a socket will be accepted but will trigger an error in the child process.</para></item.i></itemize></item.e><item.e index='3'><para>Efficiency - The author has not yet attempted a detailed performance study, but this proposal does have some theoretical inefficiencies when compared to a pure C implementation, such as <emph style="bold">bgexec</emph>:</para><itemize><item.i><para>an intermediate Tcl procedure is used to capture output from a pipe</para></item.i><item.i><para>each end of each pipe has to be wrapped in a <emph style="italic">CommandChannel</emph> before it can be passed back to the calling script, even if the pipe is just going to be used to link together two processes in a pipeline.</para></item.i></itemize></item.e></enumerate>
</section>
<section title="Related Possibilities for Future Enhancements">
<enumerate><item.e index='1'><para>For Windows, an important limitation that is not addressed by this TIP, is the lack of control over the console window settings when invoking a process. This will require changes to <emph style="italic">TclpCreateProcess</emph>.</para></item.e><item.e index='2'><para>A <emph style="bold">kill</emph> subcommand would be a useful addition to the <emph style="bold">process</emph> ensemble. On Windows, the ability to kill a child console process cleanly is related to the choice of console mode, so this issue would ideally be addressed in conjunction with item (1) above.</para></item.e><item.e index='3'><para>A command to categorise an exit status obtained from <emph style="bold">process status</emph> or <emph style="bold">process wait</emph> along similar lines to the data placed in <emph style="italic">$errorCode</emph> by <emph style="italic">TclCleanupChildren()</emph>.</para></item.e><item.e index='4'><para>Some aspects of the existing <emph style="bold">exec</emph> command depend on use of temporary files. Since this TIP transfers the high level implementation of process launching into Tcl scripts, support for creation of uniquely named temporary files, as proposed in <tipref type="text" tip="210"/>, would be useful.</para></item.e><item.e index='5'><para>The wish console on Windows could be improved, using this mechanism, so that program names typed interactively will run in the background, allowing output to be seen before the process completes.</para></item.e><item.e index='6'><para>The ability to define <emph style="italic">argv[0]</emph>, independently from the program name, would occasionally be useful. For example, some UNIX shells run as login shells when <emph style="italic">argv[0]</emph> begins with a dash.</para></item.e><item.e index='7'><para>Public C functions for invoking a process and creating a pipe wrapped in command channels.</para></item.e><item.e index='8'><para>Support for detaching process and for reaping detached processes.</para></item.e><item.e index='9'><para>The existing <emph style="bold">exit</emph> command could be duplicated in the <emph style="bold">process</emph> ensemble.</para></item.e><item.e index='10'><para>The basic form of the existing <emph style="bold">pid</emph> command, which obtains the process id of the current process, could be added to the <emph style="bold">process</emph> ensemble.</para></item.e><item.e index='11'><para>In some cases, it is more appropriate to run a child process with its streams connected to a null file rather than disconnected. Since the name of the null file is platform specific, it would be helpful to have a platform independent way of accessing the name.</para></item.e><item.e index='12'><para>An option to obtain full status information. On Windows, process exit codes are 32 bit. On UNIX, higher bits of a waitpid() status value distinguish termination via exit() from termination via an uncaught signal.</para></item.e></enumerate>
</section>
<section title="Reference Implementation">
<para>Submitted as patch 1315115 [<url ref="https://sourceforge.net/support/tracker.php?aid=1315115"/>]</para>
</section>
<section title="Copyright">
<para>This document has been placed in the public domain.</para>
</section>
</body></TIP>
