TIP 462: Add New [info ps] Ensemble for Subprocess Management

Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2017 Conference, Houston/TX, US, Oct 16-20
Send your abstracts to tclconference@googlegroups.com
by Aug 21.
Author:         Frédéric Bonnet <fredericbonnet@free.fr>
State:          Draft
Type:           Project
Vote:           Pending
Created:        23-Jan-2017
Tcl-Version:    8.7


This TIP proposes to improve Tcl's handling of subprocesses created by the exec and open commands by adding a new ::tcl::process ensemble.


This TIP is inspired by a https://github.com/flightaware/Tcl-bounties\#stop-tcl-from-eating-child-process-exit-status-gratuitously%\|%request from FlightAware%|% to fix the way Tcl currently handles child process exit status.

Subprocess creation can be either synchronous or asynchronous. In either case, a children with a non-zero return value indicates an error condition that is bubbled up to the Tcl error handling mechanism.

Synchronous subprocesses

Synchronous subprocesses are created using the exec command with no & terminal argument. Errors are raised synchronously as well.

Asynchronous subprocesses

Asynchronous subprocesses can be created using two distinct methods:

Error handling and status code

Errors are caught with the catch and try commands, with status codes given in the -errorcode options dictionary entry and the errorCode global variable in the form {CHILDKILLED pid sigName msg} / {CHILDSTATUS pid code} / {CHILDSUSP pid sigName msg}.

C-level access

The Tcl library provides the following procedures for managing subprocesses (excerpts from the Tcl documentation):

Moreover, Tcl_WaitPid is blocking unless called with the WNOHANG option.


The current implementation is lacking several key features:


A new ::tcl::process will be created:

::tcl::process subcommand ?arg ...: Subprocess management.

The following subcommand values are supported by ::tcl::process:

Additionally, ::tcl::process status accepts the following switches:


% ::tcl::process autopurge
% ::tcl::process autopurge false

% set pid1 [exec command1 a b c | command2 d e f &]
123 456
% set chan [open "|command1 a b c | command2 d e f"]
% set pid2 [pid $chan]
789 1011

% ::tcl::process list
123 456 789 1011

% ::tcl::process status
123 {CHILDSTATUS 123 0} 456 {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"} 789 {CHILDSUSP 789 SIGTTIN "background tty read"} 1011 {}

% ::tcl::process status 123
123 {CHILDSTATUS 123 0}

% ::tcl::process status 1011
1011 {}

% ::tcl::process status -wait
123 {CHILDSTATUS 123 0} 456 {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"} 789 {CHILDSUSP 789 SIGTTIN "background tty read"} 1011 {CHILDSTATUS 1011 -1}

% ::tcl::process status 1011
1011 {CHILDSTATUS 1011 -1}

% ::tcl::process purge
% exec command1 1 2 3 &
% ::tcl::process list

Rejected Alternatives

The first version proposed to implement the feature as a new ps option to the existing info command. However, almost all operations in [info] are things that just examine state, not change it, and that's a principle-of-least-astonishment that should be upheld for the sake of less experienced users.

Reference implementation



This document has been placed in the public domain.