diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rwxr-xr-x | configure | 24 | ||||
-rw-r--r-- | stream.c | 12 |
3 files changed, 48 insertions, 1 deletions
@@ -1,5 +1,18 @@ 2014-03-11 Kaz Kylheku <kaz@kylheku.com> + * configure: new test for fcntl. + + * stream.c (open_process): Fixed off-by one erroneous value of nargs, + causing memory leak of one string. Fixed memory leak on fork failure. + Fixed a deadlock that can occur in the pipe close function when + multiple pipes are in existence. This is fixed by setting the + FD_CLOEXEC flag on the pipe file descriptor. Without this, one child + process can hold another's pipe open, causing that other one not to + terminate when we're trying to shut it down, resulting in that child + blocked on a write, while we block on waitpid. + +2014-03-11 Kaz Kylheku <kaz@kylheku.com> + * stream.c (open_process): In the event of fdopen failure, kill the child process less abruptly by hitting it with SIGINT and SIGTERM, rather than with SIGKILL. Also, collect the child @@ -1330,6 +1330,30 @@ else fi # +# fcntl +# + +printf "Checking for POSIX fcntl ... " + +cat > conftest.c <<! +#include "config.h" +#include <fcntl.h> + +int main(int argc, char **argv) +{ + int err = fcntl(0, F_SETFD, FD_CLOEXEC); + return 0; +} +! + +if conftest ; then + printf "yes\n" + printf "#define HAVE_FCNTL_H 1\n" >> config.h +else + printf "no\n" +fi + +# # Check for fields inside struct tm # @@ -38,6 +38,9 @@ #if HAVE_UNISTD_H #include <unistd.h> #endif +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif #include <float.h> #if HAVE_SYS_WAIT #include <sys/wait.h> @@ -2131,7 +2134,7 @@ val open_process(val name, val mode_str, val args) int i, nargs; args = default_bool_arg(args); - nargs = c_num(length(args)); + nargs = c_num(length(args)) + 1; if (pipe(fd) == -1) { uw_throwf(file_error_s, lit("opening pipe ~a, pipe syscall failed: ~a/~s"), @@ -2151,6 +2154,9 @@ val open_process(val name, val mode_str, val args) pid = fork(); if (pid == -1) { + for (i = 0; i < nargs; i++) + free(argv[i]); + free(argv); uw_throwf(file_error_s, lit("opening pipe ~a, fork syscall failed: ~a/~s"), name, num(errno), string_utf8(strerror(errno)), nao); } @@ -2187,6 +2193,10 @@ val open_process(val name, val mode_str, val args) free(argv[i]); free(argv); +#if HAVE_FCNTL_H + fcntl(whichfd, F_SETFD, FD_CLOEXEC); +#endif + if ((f = fdopen(whichfd, utf8mode)) == 0) { int status; kill(pid, SIGINT); |