mirror of
https://git.savannah.gnu.org/git/make.git
synced 2024-12-25 05:29:46 +00:00
[SV 62145] Remove a stdin temp file on re-exec failure.
If the re-exec fails, be sure to remove a temp makefile that was created to read from stdin. * src/job.c (exec_command): Return on failure. (child_execute_job): Call exit if exec_command returns. * src/job.h (exec_command): Don't mark as NORETURN. * src/main.c (main): Unlink stdin temporary file if re-exec fails. * tests/run_make_tests.pl: Get value for ERR_nonexe_file/ERR_exe_dir. * tests/scripts/features/temp_stdin: Test that temp file unlink works.
This commit is contained in:
parent
416664b1e7
commit
949c0464a9
5 changed files with 118 additions and 21 deletions
16
src/job.c
16
src/job.c
|
@ -2309,6 +2309,7 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
|||
|
||||
/* Run the command. */
|
||||
exec_command (argv, child->environment);
|
||||
_exit (127);
|
||||
|
||||
#else /* USE_POSIX_SPAWN */
|
||||
|
||||
|
@ -2452,12 +2453,7 @@ child_execute_job (struct childbase *child, int good_stdin, char **argv)
|
|||
/* Replace the current process with one running the command in ARGV,
|
||||
with environment ENVP. This function does not return. */
|
||||
|
||||
/* EMX: This function returns the pid of the child process. */
|
||||
# ifdef __EMX__
|
||||
pid_t
|
||||
# else
|
||||
void
|
||||
# endif
|
||||
exec_command (char **argv, char **envp)
|
||||
{
|
||||
#ifdef VMS
|
||||
|
@ -2524,14 +2520,12 @@ exec_command (char **argv, char **envp)
|
|||
}
|
||||
}
|
||||
|
||||
/* return child's exit code as our exit code */
|
||||
/* Use the child's exit code as our exit code */
|
||||
exit (exit_code);
|
||||
|
||||
#else /* !WINDOWS32 */
|
||||
|
||||
# ifdef __EMX__
|
||||
pid_t pid;
|
||||
# endif
|
||||
pid_t pid = -1;
|
||||
|
||||
/* Be the user, permanently. */
|
||||
child_access ();
|
||||
|
@ -2630,11 +2624,7 @@ exec_command (char **argv, char **envp)
|
|||
break;
|
||||
}
|
||||
|
||||
# ifdef __EMX__
|
||||
return pid;
|
||||
# else
|
||||
_exit (127);
|
||||
# endif
|
||||
#endif /* !WINDOWS32 */
|
||||
#endif /* !VMS */
|
||||
}
|
||||
|
|
|
@ -81,10 +81,8 @@ pid_t child_execute_job (struct childbase *child, int good_stdin, char **argv);
|
|||
|
||||
#ifdef _AMIGA
|
||||
void exec_command (char **argv) NORETURN;
|
||||
#elif defined(__EMX__)
|
||||
int exec_command (char **argv, char **envp);
|
||||
#else
|
||||
void exec_command (char **argv, char **envp) NORETURN;
|
||||
pid_t exec_command (char **argv, char **envp);
|
||||
#endif
|
||||
|
||||
void unblock_all_sigs (void);
|
||||
|
|
|
@ -2655,10 +2655,13 @@ main (int argc, char **argv, char **envp)
|
|||
#endif
|
||||
exec_command ((char **)nargv, environ);
|
||||
#endif
|
||||
|
||||
/* We shouldn't get here but just in case. */
|
||||
jobserver_post_child(1);
|
||||
break;
|
||||
|
||||
/* Get rid of any stdin temp file. */
|
||||
if (stdin_offset >= 0)
|
||||
unlink (makefiles->list[stdin_offset]);
|
||||
|
||||
_exit (127);
|
||||
}
|
||||
|
||||
if (any_failed)
|
||||
|
|
|
@ -141,14 +141,14 @@ $ERR_command_not_found = undef;
|
|||
$ERR_read_only_file = "$!";
|
||||
}
|
||||
|
||||
$_ = `./file.out 2>/dev/null`;
|
||||
$_ = `./file.out 2>&1`;
|
||||
if ($? == 0) {
|
||||
print "Executed non-executable file! Skipping related tests.\n";
|
||||
} else {
|
||||
$ERR_nonexe_file = "$!";
|
||||
}
|
||||
|
||||
$_ = `./. 2>/dev/null`;
|
||||
$_ = `./. 2>&1`;
|
||||
if ($? == 0) {
|
||||
print "Executed directory! Skipping related tests.\n";
|
||||
} else {
|
||||
|
|
106
tests/scripts/features/temp_stdin
Normal file
106
tests/scripts/features/temp_stdin
Normal file
|
@ -0,0 +1,106 @@
|
|||
# -*-mode: perl-*-
|
||||
|
||||
$description = "Test handling of temporary file created from stdin.";
|
||||
|
||||
use File::Temp qw /tempdir/;
|
||||
|
||||
sub check_tempfile
|
||||
{
|
||||
my ($tdir) = @_;
|
||||
my @left = glob $tdir . '/Gm*';
|
||||
scalar @left == 0 && return;
|
||||
my $answer = "temporary file $left[0] is left behind\n";
|
||||
compare_output($answer, &get_logfile(1));
|
||||
}
|
||||
|
||||
create_file('input.mk', "world:=1\n");
|
||||
create_file('bye.mk', "moon:=2\n");
|
||||
|
||||
# sv 62118,62145.
|
||||
# Test that makes leaves no temp file when make code is piped to stdin and -v,
|
||||
# -h or an invalid option is specified.
|
||||
my @opts = ('-v', '-h', '--nosuchopt');
|
||||
my @exit_codes = (0, 0, 512);
|
||||
for my $i (0 .. $#opts) {
|
||||
my $tdir = tempdir(CLEANUP => 1);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
$ENV{'TMP'} = $tdir;
|
||||
close(STDIN);
|
||||
open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
|
||||
run_make_test(q!
|
||||
all:; $(info hello world)
|
||||
!,
|
||||
"$opts[$i] -f-", "/uilt for /", $exit_codes[$i]);
|
||||
check_tempfile($tdir);
|
||||
}
|
||||
|
||||
# sv 62118,62145.
|
||||
# Test that a stdin temp file is removed.
|
||||
my $tdir = tempdir(CLEANUP => 1);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
$ENV{'TMP'} = $tdir;
|
||||
close(STDIN);
|
||||
open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
|
||||
run_make_test(q!
|
||||
all:; $(info world=$(world))
|
||||
!,
|
||||
'-f-', "world=1\n#MAKE#: 'all' is up to date.\n");
|
||||
check_tempfile($tdir);
|
||||
|
||||
# sv 62118,62145.
|
||||
# Test that a stdin temp file is removed, even when make re-execs.
|
||||
# Also test that make nohors TMPDIR to create the temp file.
|
||||
my $tdir = tempdir(CLEANUP => 1);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
$ENV{'TMP'} = $tdir;
|
||||
# Ensure touching bye.mk causes re-exec.
|
||||
&utouch(-600, 'bye.mk');
|
||||
close(STDIN);
|
||||
open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
|
||||
run_make_test(q!
|
||||
include bye.mk
|
||||
all:; $(info hello)
|
||||
$(MAKE_RESTARTS)bye.mk: force; touch $@
|
||||
force:
|
||||
!,
|
||||
'-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$tdir\E/");
|
||||
check_tempfile($tdir);
|
||||
|
||||
if ($port_type eq 'UNIX') {
|
||||
# sv 62118,62145.
|
||||
# Test that a stdin temp file is removed, when execvp fails to re-exec make.
|
||||
# In order to cause execvp to fail, copy the tested make binary to the temp
|
||||
# directory and take away the 'x' bit.
|
||||
use File::Copy;
|
||||
|
||||
my $tdir = tempdir(CLEANUP => 1);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
$ENV{'TMP'} = $tdir;
|
||||
my $makecopy = "$tdir/make";
|
||||
copy("$mkpath", $makecopy);
|
||||
# Set file mode bits, because perl copy won't.
|
||||
chmod 0750, $makecopy;
|
||||
|
||||
my @make_orig = @make_command;
|
||||
@make_command = ($makecopy);
|
||||
|
||||
# Ensure touching bye.mk causes re-exec.
|
||||
&utouch(-600, 'bye.mk');
|
||||
close(STDIN);
|
||||
open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
|
||||
run_make_test("
|
||||
include bye.mk
|
||||
all:; \$(info hello)
|
||||
\$(MAKE_RESTARTS)bye.mk: force; touch \$@ && chmod -x $makecopy
|
||||
force:
|
||||
",
|
||||
"-f-", "touch bye.mk && chmod -x $makecopy\nmake: $makecopy: $ERR_nonexe_file\n", 32512);
|
||||
check_tempfile($tdir);
|
||||
|
||||
@make_command = @make_orig;
|
||||
}
|
||||
|
||||
unlink('input.mk', 'bye.mk');
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
Loading…
Reference in a new issue