diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-07-26 08:06:52 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-07-26 08:06:52 (GMT) |
commit | df1e155f688d17926a6d952abe79ea9ff0474936 (patch) | |
tree | 4f5148b75759dbe2870070abb6b0abdfcee23390 /unix/tclUnixPipe.c | |
parent | 4dd445404be4d6cc1ad17908850b79bf61b62dc7 (diff) | |
parent | 862ae1266cd494baaed59be9a1d74b66de7eaa6a (diff) | |
download | tcl-df1e155f688d17926a6d952abe79ea9ff0474936.zip tcl-df1e155f688d17926a6d952abe79ea9ff0474936.tar.gz tcl-df1e155f688d17926a6d952abe79ea9ff0474936.tar.bz2 |
Merge 8.7
Diffstat (limited to 'unix/tclUnixPipe.c')
-rw-r--r-- | unix/tclUnixPipe.c | 77 |
1 files changed, 54 insertions, 23 deletions
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 6b33576..4e8a758 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -14,10 +14,17 @@ #include "tclInt.h" #ifdef HAVE_POSIX_SPAWNP -# include <spawn.h> +# if defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2) \ + && defined(HAVE_POSIX_SPAWNATTR_SETFLAGS) \ + && !defined(HAVE_VFORK) +# include <unistd.h> +# include <spawn.h> +# else +# undef HAVE_POSIX_SPAWNP +# endif #endif -#ifdef USE_VFORK +#ifdef HAVE_VFORK #define fork vfork #endif @@ -418,6 +425,7 @@ TclpCreateProcess( size_t i; #if defined(HAVE_POSIX_SPAWNP) int childErrno; + static int use_spawn = -1; #endif errPipeIn = NULL; @@ -447,7 +455,7 @@ TclpCreateProcess( newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], TCL_INDEX_NONE, &dsArray[i]); } -#if defined(USE_VFORK) || defined(HAVE_POSIX_SPAWNP) +#if defined(HAVE_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 @@ -468,28 +476,52 @@ TclpCreateProcess( #endif #ifdef HAVE_POSIX_SPAWNP - { +#ifdef _CS_GNU_LIBC_VERSION + if (use_spawn < 0) { + char conf[32], *p; + int major = 0, minor = 0; + + use_spawn = 0; + memset(conf, 0, sizeof(conf)); + confstr(_CS_GNU_LIBC_VERSION, conf, sizeof(conf)); + p = strchr(conf, ' '); /* skip "glibc" */ + if (p != NULL) { + ++p; + if (sscanf(p, "%d.%d", &major, &minor) > 1) { + if ((major > 2) || ((major == 2) && (minor >= 24))) { + use_spawn = 1; + } + } + } + } +#endif + status = -1; + if (use_spawn) { posix_spawn_file_actions_t actions; posix_spawnattr_t attr; + sigset_t sigs; 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 - ); + sigfillset(&sigs); + sigdelset(&sigs, SIGKILL); + sigdelset(&sigs, SIGSTOP); + + posix_spawnattr_setflags(&attr, + POSIX_SPAWN_SETSIGDEF +#ifdef POSIX_SPAWN_USEVFORK + | POSIX_SPAWN_USEVFORK +#endif + ); + posix_spawnattr_setsigdefault(&attr, &sigs); 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; - + status = posix_spawnp(&pid, newArgv[0], &actions, &attr, + newArgv, environ); + childErrno = errno; posix_spawn_file_actions_destroy(&actions); posix_spawnattr_destroy(&attr); @@ -499,11 +531,13 @@ TclpCreateProcess( * - pid == -1: error * - pid > 0: parent process * - * Mimic fork semantics to minimize changes below + * Mimic fork semantics to minimize changes below, + * but retry with fork() as last ressort. */ - if (status != 0) { - pid = -1; - } + } + if (status != 0) { + pid = fork(); + childErrno = errno; } #else pid = fork(); @@ -559,12 +593,9 @@ TclpCreateProcess( 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 +#endif Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't fork child process: %s", Tcl_PosixError(interp))); -#endif goto error; } |