mirror of
https://github.com/mirror/make.git
synced 2025-01-17 07:40:24 +08:00
[SV 63157] Ensure temporary files are removed when signaled
Original patch from Dmitry Goncharov <dgoncharov@users.sf.net>. When handling a fatal signal ensure the temporary files for stdin and the jobserver fifo (if in use) are deleted. * src/makeint.h (temp_stdin_unlink): Declare a new method. * src/main.c (temp_stdin_unlink): Delete the stdin temporary file if it exists. If the unlink fails and we're not handling a signal then show an error. (main): Call temp_stdin_unlink() instead of unlinking by hand. * src/commands.c (fatal_error_signal): Invoke cleanup methods if we're handling a fatal signal. * tests/scripts/features/output-sync: Test signal handling during output sync and jobserver with FIFO. * tests/scripts/features/temp_stdin: Test signal handling when makefiles are read from stdin.
This commit is contained in:
parent
383eb3a923
commit
18c4b508ef
@ -16,6 +16,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "makeint.h"
|
||||
#include "filedef.h"
|
||||
#include "os.h"
|
||||
#include "dep.h"
|
||||
#include "variable.h"
|
||||
#include "job.h"
|
||||
@ -532,6 +533,10 @@ fatal_error_signal (int sig)
|
||||
It is blocked now while we run this handler. */
|
||||
signal (sig, SIG_DFL);
|
||||
|
||||
temp_stdin_unlink ();
|
||||
osync_clear ();
|
||||
jobserver_clear ();
|
||||
|
||||
/* A termination signal won't be sent to the entire
|
||||
process group, but it means we want to kill the children. */
|
||||
|
||||
|
39
src/main.c
39
src/main.c
@ -1137,6 +1137,23 @@ reset_jobserver (void)
|
||||
jobserver_auth = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
temp_stdin_unlink ()
|
||||
{
|
||||
/* This function is called from a signal handler. Keep async-signal-safe.
|
||||
If there is a temp file from reading from stdin, get rid of it. */
|
||||
if (stdin_offset >= 0)
|
||||
{
|
||||
const char *nm = makefiles->list[stdin_offset];
|
||||
int r = 0;
|
||||
|
||||
stdin_offset = -1;
|
||||
EINTRLOOP(r, unlink (nm));
|
||||
if (r < 0 && errno != ENOENT && !handling_fatal_signal)
|
||||
perror_with_name (_("unlink (temporary file): "), nm);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _AMIGA
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@ -2776,9 +2793,7 @@ main (int argc, char **argv, char **envp)
|
||||
#endif
|
||||
jobserver_post_child(1);
|
||||
|
||||
/* Get rid of any stdin temp file. */
|
||||
if (stdin_offset >= 0)
|
||||
unlink (makefiles->list[stdin_offset]);
|
||||
temp_stdin_unlink ();
|
||||
|
||||
_exit (127);
|
||||
}
|
||||
@ -2804,15 +2819,7 @@ main (int argc, char **argv, char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is a temp file from reading a makefile from stdin, get rid of
|
||||
it now. */
|
||||
if (stdin_offset >= 0)
|
||||
{
|
||||
const char *nm = makefiles->list[stdin_offset];
|
||||
if (unlink (nm) < 0 && errno != ENOENT)
|
||||
perror_with_name (_("unlink (temporary file): "), nm);
|
||||
stdin_offset = -1;
|
||||
}
|
||||
temp_stdin_unlink ();
|
||||
|
||||
/* If there were no command-line goals, use the default. */
|
||||
if (goals == 0)
|
||||
@ -3731,13 +3738,7 @@ die (int status)
|
||||
print_version ();
|
||||
|
||||
/* Get rid of a temp file from reading a makefile from stdin. */
|
||||
if (stdin_offset >= 0)
|
||||
{
|
||||
const char *nm = makefiles->list[stdin_offset];
|
||||
if (unlink (nm) < 0 && errno != ENOENT)
|
||||
perror_with_name (_("unlink (temporary file): "), nm);
|
||||
stdin_offset = -1;
|
||||
}
|
||||
temp_stdin_unlink ();
|
||||
|
||||
/* Wait for children to die. */
|
||||
err = (status != 0);
|
||||
|
@ -545,6 +545,7 @@ void out_of_memory () NORETURN;
|
||||
(_f), (_n), (_s))
|
||||
|
||||
void decode_env_switches (const char*, size_t line);
|
||||
void temp_stdin_unlink (void);
|
||||
void die (int) NORETURN;
|
||||
void pfatal_with_name (const char *) NORETURN;
|
||||
void perror_with_name (const char *, const char *);
|
||||
|
@ -338,5 +338,28 @@ all:: ; @./foo bar baz
|
||||
'-O', "#MAKE#: ./foo: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#:2: all] Error 127\n", 512);
|
||||
}
|
||||
|
||||
if ($port_type eq 'UNIX') {
|
||||
# POSIX doesn't require sh to set PPID so test this
|
||||
my $cmd = create_command();
|
||||
add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
|
||||
my $fout = 'ppidtest.out';
|
||||
run_command_with_output($fout, @$cmd);
|
||||
$_ = read_file_into_string($fout);
|
||||
chomp($_);
|
||||
if (/^[0-9]+$/) {
|
||||
use POSIX ();
|
||||
# SV 63157.
|
||||
# Test that make removes temporary files, even when a signal is received.
|
||||
# The general test_driver postprocessing will ensure the temporary file used
|
||||
# to synchronize output and the jobserver fifo are both removed.
|
||||
run_make_test(q!
|
||||
pid:=$(shell echo $$PPID)
|
||||
all:; @kill -TERM $(pid)
|
||||
!, '-O -j2', "", POSIX::SIGTERM);
|
||||
}
|
||||
|
||||
unlink($fout);
|
||||
}
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
1;
|
||||
|
@ -46,6 +46,35 @@ force:
|
||||
'-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$temppath\E/");
|
||||
|
||||
if ($port_type eq 'UNIX') {
|
||||
# POSIX doesn't require sh to set PPID so test this
|
||||
my $cmd = create_command();
|
||||
add_options($cmd, '-f', '/dev/null', '-E', q!all:;@echo $$PPID!);
|
||||
my $fout = 'ppidtest.out';
|
||||
run_command_with_output($fout, @$cmd);
|
||||
$_ = read_file_into_string($fout);
|
||||
chomp($_);
|
||||
if (/^[0-9]+$/) {
|
||||
use POSIX ();
|
||||
|
||||
# sv 63157.
|
||||
# Test that make removes the temporary file which holds make code from stdin,
|
||||
# even when a signal is received.
|
||||
# include bye.mk and bye.mk: rule is needed to cause make to keep the temporary
|
||||
# file for re-exec. Without re-exec make will remove the file before the signal
|
||||
# arrives.
|
||||
&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
|
||||
pid:=$(shell echo $$PPID)
|
||||
all:;
|
||||
bye.mk: force; @kill -TERM $(pid)
|
||||
force:
|
||||
!, '-f-', "", POSIX::SIGTERM);
|
||||
}
|
||||
unlink($fout);
|
||||
|
||||
# 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
|
||||
|
Loading…
Reference in New Issue
Block a user