Tcl Source Code

View Ticket
Login
Ticket UUID: 21dbc600ae0a005a7f879a05580550a8da257b14
Title: exec hangs, iff stdin & stdout both were previously closed.
Type: Bug Created on: 2022-12-06 11:45:49
Submitter: avl42 Assigned to: nobody
Subsystem: 16. Commands A-H Severity: Severe
Priority: 5 Medium Last modified: 2026-10-20 21:28:10
Status: Open Closed by: nobody
Resolution: None Closed on:
Version: 8.6.18, 9.0.5, 9.1.0
Description:
simplest test script:
   close stdin; close stdout; exec true

Workaround (assuming that original stdin & -out just need to be closed):
   close stdin; close stdout; open /dev/null r; exec true

In either case: exec first creates a pipe, and while the child runs,
the parent waits on that pipe for EOF (probably to be initiated
from another thread).

With at least one of stdin or stdout NOT closed (or re-opened afterwards),
the EOF on that pipe is seen, but with BOTH stdin/-out closed, nothing
ever closes the write-end of the pipe.

PS: that pipe is NOT the one by which the main process communicates to the child.
User Comments:
serhiy.storchaka added on 2026-10-13 18:34:38:

Still hangs with 8.6.17, 9.0 and 9.1. With stdin and stdout closed, the pipe for the output of the child gets descriptors 0 and 1, and TclpCloseFile() never closes 0, 1 and 2, so the parent keeps the write end open and never sees the end of the output.

Proposed fix in branch exec-closed-stdio: move pipes and files created for a pipeline above descriptor 2. Test exec-23.1.


jan.nijtmans added on 2026-10-20 20:53:48:

I'm seeing this compiler warning, even though it appears to work fine:

unix/tclUnixPipe.c:469:13: warning: variable ‘errPipeIn’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
  469 |     TclFile errPipeIn, errPipeOut;
      |             ^~~~~~~~~
unix/tclUnixPipe.c:469:24: warning: variable ‘errPipeOut’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
  469 |     TclFile errPipeIn, errPipeOut;
      |                        ^~~~~~~~~~


jan.nijtmans added on 2026-10-20 21:03:20:

This warning is caused by the line

pid = fork();

in line 602


serhiy.storchaka added on 2026-10-20 21:28:10:

The warning is not new in this branch: TclpCreateProcess() is unchanged, but unix/tclUnixPipe.c has #define fork vfork when HAVE_VFORK is set, so pid = fork(); is really vfork(), after which gcc warns about locals that may be clobbered. dsArray and newArgv there were already volatile for this reason, errPipeIn/errPipeOut were not.

Fixed in [4af19e7744] on the branch: they are volatile now (TclpCreatePipe() fills plain temporaries). My gcc 15 never showed the warning, so please check that it is gone with yours.