diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-07-24 13:32:43 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-07-24 13:32:43 (GMT) |
commit | 545fe029f600cd7e087a48259b86e1c6c00793a2 (patch) | |
tree | 90913b237960e4b5ea25f1f66cbb08eaa99064e6 /unix/tclUnixPipe.c | |
parent | a3581baf860f2a375a2e47178c6c15eac3f919aa (diff) | |
parent | 399309020d7f8caf7b710a6a41601159cdc32e30 (diff) | |
download | tcl-545fe029f600cd7e087a48259b86e1c6c00793a2.zip tcl-545fe029f600cd7e087a48259b86e1c6c00793a2.tar.gz tcl-545fe029f600cd7e087a48259b86e1c6c00793a2.tar.bz2 |
Merge 8.7
Diffstat (limited to 'unix/tclUnixPipe.c')
-rw-r--r-- | unix/tclUnixPipe.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index c1fae5d..6b33576 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -13,6 +13,10 @@ #include "tclInt.h" +#ifdef HAVE_POSIX_SPAWNP +# include <spawn.h> +#endif + #ifdef USE_VFORK #define fork vfork #endif @@ -412,6 +416,9 @@ TclpCreateProcess( char **newArgv; int pid; size_t i; +#if defined(HAVE_POSIX_SPAWNP) + int childErrno; +#endif errPipeIn = NULL; errPipeOut = NULL; @@ -440,7 +447,7 @@ TclpCreateProcess( newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], TCL_INDEX_NONE, &dsArray[i]); } -#ifdef USE_VFORK +#if defined(USE_VFORK) || defined(HAVE_POSIX_SPAWNP) /* * After vfork(), do not call code in the child that changes global state, * because it is using the parent's memory space at that point and writes @@ -453,14 +460,54 @@ TclpCreateProcess( Tcl_GetStdChannel(TCL_STDIN); } if (!outputFile) { - Tcl_GetStdChannel(TCL_STDOUT); + Tcl_GetStdChannel(TCL_STDOUT); } if (!errorFile) { - Tcl_GetStdChannel(TCL_STDERR); + Tcl_GetStdChannel(TCL_STDERR); } #endif +#ifdef HAVE_POSIX_SPAWNP + { + posix_spawn_file_actions_t actions; + posix_spawnattr_t attr; + + posix_spawn_file_actions_init(&actions); + posix_spawnattr_init(&attr); + + posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF| +# ifdef POSIX_SPAWN_USEVFORK + POSIX_SPAWN_USEVFORK +# else + 0 +# endif + ); + + posix_spawn_file_actions_adddup2(&actions, GetFd(inputFile), 0); + posix_spawn_file_actions_adddup2(&actions, GetFd(outputFile), 1); + posix_spawn_file_actions_adddup2(&actions, GetFd(errorFile), 2); + + status = posix_spawnp(&pid, newArgv[0], &actions, &attr, newArgv, environ); + childErrno = status; + + posix_spawn_file_actions_destroy(&actions); + posix_spawnattr_destroy(&attr); + + /* + * Fork semantics: + * - pid == 0: child process + * - pid == -1: error + * - pid > 0: parent process + * + * Mimic fork semantics to minimize changes below + */ + if (status != 0) { + pid = -1; + } + } +#else pid = fork(); +#endif if (pid == 0) { size_t len; int joinThisError = errorFile && (errorFile == outputFile); @@ -510,8 +557,14 @@ TclpCreateProcess( TclStackFree(interp, dsArray); if (pid == -1) { +#ifdef HAVE_POSIX_SPAWNP + errno = childErrno; + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't execute \"%s\": %s", argv[0], Tcl_PosixError(interp))); +#else Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't fork child process: %s", Tcl_PosixError(interp))); +#endif goto error; } |