summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2019-12-27 01:27:09 -0500
committerPaul Smith <psmith@gnu.org>2019-12-27 01:37:17 -0500
commite64674b718600bd4fad0b5ac1cc37eb89fba5ef7 (patch)
tree7bb82458a418fdf9b3af48954b76e0bbdddc29d4
parent564fb212a727a6b6773f454d192a7e02de62d2ef (diff)
downloadmake-e64674b718600bd4fad0b5ac1cc37eb89fba5ef7.tar.gz
[SV 57022] Avoid posix_spawn which fails asynchronously
Avoid using posix_spawn implementations that fail asynchronously when the spawned program can't be invoked: this means instead of getting an error such as "No such file or directory" we get just "Exit 127". Original implementation of the configure.ac macro provided by Martin Dorey <martin.dorey@hds.com> Original implementation of the regression tests provided by Dmitry Goncharov <dgoncharov@users.sf.net> * configure.ac: Test whether posix_spawn fails asynchronously. In a cross-compilation environment, assume that it does not. If we detect that it does, fall back to fork/exec. * tests/scripts/features/exec: Add regression tests for different shebang invocation methods.
-rw-r--r--configure.ac23
-rw-r--r--tests/scripts/features/exec63
2 files changed, 85 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index af58c1b4..5daff11e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -371,7 +371,28 @@ AC_ARG_ENABLE([posix-spawn],
AS_CASE([/$ac_cv_header_spawn/$ac_cv_func_posix_spawn/],
[*/no/*], [make_cv_posix_spawn=no])
-AS_CASE([/$make_cv_posix_spawn/$user_posix_spawn/],
+AS_IF([test "$make_cv_posix_spawn" = yes],
+ AC_CACHE_CHECK([for posix_spawn that fails synchronously],
+ [make_cv_synchronous_posix_spawn],
+ [make_cv_synchronous_posix_spawn=no
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #include <spawn.h>
+ #include <string.h>
+
+ extern char **environ;
+
+ int main() {
+ char* path = strdup("./non-existent");
+ char *argv[[2]];
+ argv[[0]] = path;
+ argv[[1]] = 0;
+ return posix_spawn(0, path, 0, 0, argv, environ);
+ }]])],
+ [make_cv_synchronous_posix_spawn=no],
+ [make_cv_synchronous_posix_spawn=yes],
+ [make_cv_synchronous_posix_spawn="no (cross-compiling)"])]))
+
+AS_CASE([/$user_posix_spawn/$make_cv_posix_spawn/$make_cv_synchronous_posix_spawn/],
[*/no/*], [make_cv_posix_spawn=no],
[AC_DEFINE(USE_POSIX_SPAWN, 1, [Define to 1 to use posix_spawn().])
])
diff --git a/tests/scripts/features/exec b/tests/scripts/features/exec
new file mode 100644
index 00000000..4b7911be
--- /dev/null
+++ b/tests/scripts/features/exec
@@ -0,0 +1,63 @@
+# -*-perl-*-
+
+use warnings;
+
+my $description = "Test that make can execute binaries as well as scripts with"
+ ." various shabangs and without a shebang";
+my $details = "The various shells that this test uses are the default "
+ ."/bin/sh, $origENV{SHELL} and the perl interpreter that is "
+ ." executing this test program. The shells are used for the value"
+ ." of SHELL inside the test makefile and also as a shebang in the"
+ ." executed script. There is also a test which executes a script"
+ ." that has no shebang.";
+
+# Only bother with this on UNIX systems
+$port_type eq 'UNIX' or return -1;
+
+my $usersh = $origENV{SHELL};
+my $answer = 'hello, world';
+
+my @shebangs = ('', '#!/bin/sh', "#!$usersh", "#!$perl_name");
+my @shells = ('', 'SHELL=/bin/sh', "SHELL=$usersh");
+
+# tests [0-11]
+# Have a makefile with various SHELL= exec a shell program with varios
+# shebangs or without a shebang at all.
+my $stem = './exec.cmd';
+my $k = 0;
+for my $shebang (@shebangs) {
+ for my $shell (@shells) {
+ my $cmd = $k ? "$stem.$k" : $stem;
+ ++$k;
+ unlink $cmd;
+ open(CMD,"> $cmd");
+ print CMD "$shebang\n";
+ print CMD "printf \"$answer\\n\";\n";
+ close(CMD);
+ chmod 0700, $cmd;
+
+ run_make_test(q!
+all:; @$(CMD)
+!, "$shell CMD=$cmd", "$answer\n");
+
+ rmfiles($cmd);
+ }
+}
+
+# tests [12-14]
+# Exec a binary from a makefile that has SHELL=.
+for my $shell (@shells) {
+ run_make_test(q!
+all:; @#PERL# -e 'printf "$(ANSWER)\n"';
+!, "$shell ANSWER='$answer'", "$answer\n");
+}
+
+# test 15
+# Use perl as a shell.
+run_make_test(q!
+SHELL = #PERL#
+.SHELLFLAGS = -e
+all:; @printf "$(ANSWER)\n";
+!, "ANSWER='$answer'", "$answer\n");
+
+1;