diff options
Diffstat (limited to 'unix')
| -rw-r--r-- | unix/Makefile.in | 3 | ||||
| -rwxr-xr-x | unix/configure | 186 | ||||
| -rw-r--r-- | unix/configure.ac | 3 | ||||
| -rw-r--r-- | unix/tcl.m4 | 37 | ||||
| -rw-r--r-- | unix/tcl.pc.in | 4 | ||||
| -rw-r--r-- | unix/tclConfig.h.in | 24 | ||||
| -rw-r--r-- | unix/tclUnixFCmd.c | 5 | ||||
| -rw-r--r-- | unix/tclUnixPipe.c | 92 | ||||
| -rw-r--r-- | unix/tclUnixPort.h | 28 |
9 files changed, 294 insertions, 88 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in index d35074e..2068c86 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -396,8 +396,7 @@ GENERIC_HDRS = \ $(GENERIC_DIR)/tclPatch.h \ $(GENERIC_DIR)/tclPlatDecls.h \ $(GENERIC_DIR)/tclPort.h \ - $(GENERIC_DIR)/tclRegexp.h \ - $(GENERIC_DIR)/tclArithSeries.h + $(GENERIC_DIR)/tclRegexp.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ diff --git a/unix/configure b/unix/configure index 3f93ef3..c0a5575 100755 --- a/unix/configure +++ b/unix/configure @@ -737,6 +737,8 @@ RANLIB TOMMATH_INCLUDE TOMMATH_SRCS TOMMATH_OBJS +TCL_PC_CFLAGS +TCL_PC_REQUIRES_PRIVATE ZLIB_INCLUDE ZLIB_SRCS ZLIB_OBJS @@ -5139,6 +5141,10 @@ fi if test $libtommath_ok = yes then : + TCL_PC_REQUIRES_PRIVATE='libtommath >= 1.2.0,' + + TCL_PC_CFLAGS='-DTCL_WITH_EXTERNAL_TOMMATH' + printf "%s\n" "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h @@ -7323,6 +7329,33 @@ printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h fi + # Check for vfork, posix_spawnp() and friends unconditionally + ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork" +if test "x$ac_cv_func_vfork" = xyes +then : + printf "%s\n" "#define HAVE_VFORK 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp" +if test "x$ac_cv_func_posix_spawnp" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "posix_spawn_file_actions_adddup2" "ac_cv_func_posix_spawn_file_actions_adddup2" +if test "x$ac_cv_func_posix_spawn_file_actions_adddup2" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "posix_spawnattr_setflags" "ac_cv_func_posix_spawnattr_setflags" +if test "x$ac_cv_func_posix_spawnattr_setflags" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWNATTR_SETFLAGS 1" >>confdefs.h + +fi + + # FIXME: This subst was left in only because the TCL_DL_LIBS # entry in tclConfig.sh uses it. It is not clear why someone # would use TCL_DL_LIBS instead of TCL_LIBS. @@ -7486,6 +7519,56 @@ printf "%s\n" "#define _ISOC99_SOURCE 1" >>confdefs.h fi + if test ${tcl_cv_flag__file_offset_bits+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main (void) +{ +switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + tcl_cv_flag__file_offset_bits=no +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include <sys/stat.h> +int +main (void) +{ +switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + tcl_cv_flag__file_offset_bits=yes +else $as_nop + tcl_cv_flag__file_offset_bits=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then + +printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h + + tcl_flags="$tcl_flags _FILE_OFFSET_BITS" + fi + + if test ${tcl_cv_flag__largefile64_source+y} then : printf %s "(cached) " >&6 @@ -7586,9 +7669,9 @@ printf "%s\n" "yes" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } # Now check for auxiliary declarations - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 -printf %s "checking for struct dirent64... " >&6; } -if test ${tcl_cv_struct_dirent64+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 +printf %s "checking for 64-bit time_t... " >&6; } +if test ${tcl_cv_time_t_64+y} then : printf %s "(cached) " >&6 else $as_nop @@ -7596,34 +7679,66 @@ else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <sys/types.h> -#include <dirent.h> int main (void) { -struct dirent64 p; +switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - tcl_cv_struct_dirent64=yes + tcl_cv_time_t_64=yes else $as_nop - tcl_cv_struct_dirent64=no + tcl_cv_time_t_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 -printf "%s\n" "$tcl_cv_struct_dirent64" >&6; } - if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 +printf "%s\n" "$tcl_cv_time_t_64" >&6; } + if test "x${tcl_cv_time_t_64}" = "xno" ; then + # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 + # which SC_TCL_EARLY_FLAGS has defined if necessary. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 +printf %s "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } +if test ${tcl_cv__time_bits+y} +then : + printf %s "(cached) " >&6 +else $as_nop -printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _TIME_BITS 64 +#include <sys/types.h> +int +main (void) +{ +switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + tcl_cv__time_bits=yes +else $as_nop + tcl_cv__time_bits=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 +printf "%s\n" "$tcl_cv__time_bits" >&6; } + if test "x${tcl_cv__time_bits}" = "xyes" ; then + +printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h + fi fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 -printf %s "checking for DIR64... " >&6; } -if test ${tcl_cv_DIR64+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 +printf %s "checking for struct dirent64... " >&6; } +if test ${tcl_cv_struct_dirent64+y} then : printf %s "(cached) " >&6 else $as_nop @@ -7635,60 +7750,60 @@ else $as_nop int main (void) { -struct dirent64 *p; DIR64 d = opendir64("."); - p = readdir64(d); rewinddir64(d); closedir64(d); +struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - tcl_cv_DIR64=yes + tcl_cv_struct_dirent64=yes else $as_nop - tcl_cv_DIR64=no + tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 -printf "%s\n" "$tcl_cv_DIR64" >&6; } - if test "x${tcl_cv_DIR64}" = "xyes" ; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 +printf "%s\n" "$tcl_cv_struct_dirent64" >&6; } + if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then -printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h +printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 -printf %s "checking for struct stat64... " >&6; } -if test ${tcl_cv_struct_stat64+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 +printf %s "checking for DIR64... " >&6; } +if test ${tcl_cv_DIR64+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> int main (void) { -struct stat64 p; - +struct dirent64 *p; DIR64 d = opendir64("."); + p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - tcl_cv_struct_stat64=yes + tcl_cv_DIR64=yes else $as_nop - tcl_cv_struct_stat64=no + tcl_cv_DIR64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 -printf "%s\n" "$tcl_cv_struct_stat64" >&6; } - if test "x${tcl_cv_struct_stat64}" = "xyes" ; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 +printf "%s\n" "$tcl_cv_DIR64" >&6; } + if test "x${tcl_cv_DIR64}" = "xyes" ; then -printf "%s\n" "#define HAVE_STRUCT_STAT64 1" >>confdefs.h +printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h fi @@ -10072,9 +10187,6 @@ fi fi -printf "%s\n" "#define USE_VFORK 1" >>confdefs.h - - printf "%s\n" "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h diff --git a/unix/configure.ac b/unix/configure.ac index f7538c3..633b568 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -185,6 +185,8 @@ if test x"${libtommath_ok}" = x -o x"${libtommath_ok}" != xno; then libtommath_ok=no])]) fi AS_IF([test $libtommath_ok = yes], [ + AC_SUBST(TCL_PC_REQUIRES_PRIVATE, ['libtommath >= 1.2.0,']) + AC_SUBST(TCL_PC_CFLAGS, ['-DTCL_WITH_EXTERNAL_TOMMATH']) AC_DEFINE(TCL_WITH_EXTERNAL_TOMMATH, 1, [Tcl with external libtommath]) ], [ AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}]) @@ -540,7 +542,6 @@ if test "`uname -s`" = "Darwin" ; then AC_CHECK_HEADERS(libkern/OSAtomic.h) AC_CHECK_FUNCS(OSSpinLockLock) fi - AC_DEFINE(USE_VFORK, 1, [Should we use vfork() instead of fork()?]) AC_DEFINE(TCL_LOAD_FROM_MEMORY, 1, [Can this platform load code from memory?]) AC_DEFINE(TCL_WIDE_CLICKS, 1, diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 9dc39f2..fca47cc 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1877,6 +1877,9 @@ dnl # preprocessing tests use only CPPFLAGS. AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],) + # Check for vfork, posix_spawnp() and friends unconditionally + AC_CHECK_FUNCS(vfork posix_spawnp posix_spawn_file_actions_adddup2 posix_spawnattr_setflags) + # FIXME: This subst was left in only because the TCL_DL_LIBS # entry in tclConfig.sh uses it. It is not clear why someone # would use TCL_DL_LIBS instead of TCL_LIBS. @@ -2294,6 +2297,7 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [ # # Might define the following vars: # _ISOC99_SOURCE +# _FILE_OFFSET_BITS # _LARGEFILE64_SOURCE # #-------------------------------------------------------------------- @@ -2301,12 +2305,12 @@ AC_DEFUN([SC_TCL_LINK_LIBS], [ AC_DEFUN([SC_TCL_EARLY_FLAG],[ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])], - [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ 1 + [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[ ]$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)])) if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then - AC_DEFINE($1, 1, [Add the ]$1[ flag when building]) + AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building]) tcl_flags="$tcl_flags $1" fi ]) @@ -2316,6 +2320,8 @@ AC_DEFUN([SC_TCL_EARLY_FLAGS],[ tcl_flags="" SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) + SC_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include <sys/stat.h>], + [switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64) SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>], [struct stat64 buf; int i = stat64("/", &buf);]) if test "x${tcl_flags}" = "x" ; then @@ -2338,8 +2344,8 @@ AC_DEFUN([SC_TCL_EARLY_FLAGS],[ # Might define the following vars: # TCL_WIDE_INT_IS_LONG # HAVE_STRUCT_DIRENT64, HAVE_DIR64 -# HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T +# _TIME_BITS # #-------------------------------------------------------------------- @@ -2359,6 +2365,23 @@ AC_DEFUN([SC_TCL_64BIT_FLAGS], [ else AC_MSG_RESULT([no]) # Now check for auxiliary declarations + AC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], + [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], + [tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])]) + if test "x${tcl_cv_time_t_64}" = "xno" ; then + # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 + # which SC_TCL_EARLY_FLAGS has defined if necessary. + AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64 +#include <sys/types.h>]], + [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], + [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])]) + if test "x${tcl_cv__time_bits}" = "xyes" ; then + AC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.]) + fi + fi + AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> #include <dirent.h>]], [[struct dirent64 p;]])], @@ -2376,14 +2399,6 @@ AC_DEFUN([SC_TCL_64BIT_FLAGS], [ AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in <sys/types.h>?]) fi - AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/stat.h>]], [[struct stat64 p; -]])], - [tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])]) - if test "x${tcl_cv_struct_stat64}" = "xyes" ; then - AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?]) - fi - AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ diff --git a/unix/tcl.pc.in b/unix/tcl.pc.in index 5f90c41..9c6da82 100644 --- a/unix/tcl.pc.in +++ b/unix/tcl.pc.in @@ -10,7 +10,7 @@ Name: Tool Command Language Description: Tcl is a powerful, easy-to-learn dynamic programming language, suitable for a wide range of uses. URL: https://www.tcl-lang.org/ Version: @TCL_VERSION@@TCL_PATCH_LEVEL@ -Requires.private: zlib >= 1.2.3, libtommath >= 1.2.0 +Requires.private: @TCL_PC_REQUIRES_PRIVATE@ zlib >= 1.2.3 Libs: -L${libdir} @TCL_LIB_FLAG@ @TCL_STUB_LIB_FLAG@ Libs.private: @TCL_LIBS@ -Cflags: -I${includedir} +Cflags: -I${includedir} @TCL_PC_CFLAGS@ diff --git a/unix/tclConfig.h.in b/unix/tclConfig.h.in index fe2c6d9..8500afb 100644 --- a/unix/tclConfig.h.in +++ b/unix/tclConfig.h.in @@ -181,6 +181,15 @@ /* Define to 1 if you have the `OSSpinLockLock' function. */ #undef HAVE_OSSPINLOCKLOCK +/* Define to 1 if you have the `posix_spawnattr_setflags' function. */ +#undef HAVE_POSIX_SPAWNATTR_SETFLAGS + +/* Define to 1 if you have the `posix_spawnp' function. */ +#undef HAVE_POSIX_SPAWNP + +/* Define to 1 if you have the `posix_spawn_file_actions_adddup2' function. */ +#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 + /* Should we use pselect()? */ #undef HAVE_PSELECT @@ -229,9 +238,6 @@ /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #undef HAVE_STRUCT_SOCKADDR_STORAGE -/* Is 'struct stat64' in <sys/stat.h>? */ -#undef HAVE_STRUCT_STAT64 - /* Define to 1 if `st_blksize' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE @@ -295,6 +301,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID @@ -450,9 +459,6 @@ /* Should we use FIONBIO? */ #undef USE_FIONBIO -/* Should we use vfork() instead of fork()? */ -#undef USE_VFORK - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD @@ -471,6 +477,9 @@ /* Are Darwin SUSv3 extensions available? */ #undef _DARWIN_C_SOURCE +/* Add the _FILE_OFFSET_BITS flag when building */ +#undef _FILE_OFFSET_BITS + /* Add the _ISOC99_SOURCE flag when building */ #undef _ISOC99_SOURCE @@ -489,6 +498,9 @@ /* Do we want the thread-safe OS API? */ #undef _THREAD_SAFE +/* _TIME_BITS=64 enables 64-bit time_t. */ +#undef _TIME_BITS + /* Do we want to use the XOPEN network library? */ #undef _XOPEN_SOURCE diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index b260cf4..dce71c4 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -266,10 +266,7 @@ MODULE_SCOPE long tclMacOSXDarwinRelease; #endif /* NO_REALPATH */ #ifdef HAVE_FTS -#if defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) -/* fts doesn't do stat64 */ -# define noFtsStat 1 -#elif defined(__APPLE__) && defined(__LP64__) && \ +#if defined(__APPLE__) && defined(__LP64__) && \ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ MAC_OS_X_VERSION_MIN_REQUIRED < 1050 /* diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index c1fae5d..4e8a758 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -13,7 +13,18 @@ #include "tclInt.h" -#ifdef USE_VFORK +#ifdef HAVE_POSIX_SPAWNP +# 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 HAVE_VFORK #define fork vfork #endif @@ -412,6 +423,10 @@ TclpCreateProcess( char **newArgv; int pid; size_t i; +#if defined(HAVE_POSIX_SPAWNP) + int childErrno; + static int use_spawn = -1; +#endif errPipeIn = NULL; errPipeOut = NULL; @@ -440,7 +455,7 @@ TclpCreateProcess( newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], TCL_INDEX_NONE, &dsArray[i]); } -#ifdef USE_VFORK +#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 @@ -453,14 +468,80 @@ 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 +#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); + 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 = errno; + 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, + * but retry with fork() as last ressort. + */ + } + if (status != 0) { + pid = fork(); + childErrno = errno; + } +#else pid = fork(); +#endif if (pid == 0) { size_t len; int joinThisError = errorFile && (errorFile == outputFile); @@ -510,6 +591,9 @@ TclpCreateProcess( TclStackFree(interp, dsArray); if (pid == -1) { +#ifdef HAVE_POSIX_SPAWNP + errno = childErrno; +#endif Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't fork child process: %s", Tcl_PosixError(interp))); goto error; diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index 33c8971..cdc67d2 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -115,10 +115,6 @@ extern "C" { #ifdef __cplusplus } #endif -#elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) -# define TclOSfstat(fd, buf) fstat64(fd, (struct stat64 *)buf) -# define TclOSstat(name, buf) stat64(name, (struct stat64 *)buf) -# define TclOSlstat(name,buf) lstat64(name, (struct stat64 *)buf) #else # define TclOSfstat(fd, buf) fstat(fd, (struct stat *)buf) # define TclOSstat(name, buf) stat(name, (struct stat *)buf) @@ -609,23 +605,13 @@ extern char ** environ; defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050 # warning "Weak import of 64-bit CoreFoundation is not supported, will not run on Mac OS X < 10.5." # endif - -/* - *--------------------------------------------------------------------------- - * At present, using vfork() instead of fork() causes execve() to fail - * intermittently on Darwin x86_64. rdar://4685553 - *--------------------------------------------------------------------------- - */ - -# if defined(__x86_64__) && !defined(FIXED_RDAR_4685553) -# undef USE_VFORK -# endif /* __x86_64__ */ -/* Workaround problems with vfork() when building with llvm-gcc-4.2 */ -# if defined (__llvm__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 2 || \ - (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0)))) -# undef USE_VFORK -# endif /* __llvm__ */ + /* + * For now, test exec-17.1 fails (I/O setup after closing stdout) with + * posix_spawnp(), but the classic implementation (based on fork()+execvp()) + * works well under macOS. + */ +# undef HAVE_POSIX_SPAWNP +# undef HAVE_VFORK #endif /* __APPLE__ */ /* |
