mirror of
https://github.com/mirror/make.git
synced 2025-03-29 05:20:28 +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 "makeint.h"
|
||||||
#include "filedef.h"
|
#include "filedef.h"
|
||||||
|
#include "os.h"
|
||||||
#include "dep.h"
|
#include "dep.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
#include "job.h"
|
#include "job.h"
|
||||||
@ -532,6 +533,10 @@ fatal_error_signal (int sig)
|
|||||||
It is blocked now while we run this handler. */
|
It is blocked now while we run this handler. */
|
||||||
signal (sig, SIG_DFL);
|
signal (sig, SIG_DFL);
|
||||||
|
|
||||||
|
temp_stdin_unlink ();
|
||||||
|
osync_clear ();
|
||||||
|
jobserver_clear ();
|
||||||
|
|
||||||
/* A termination signal won't be sent to the entire
|
/* A termination signal won't be sent to the entire
|
||||||
process group, but it means we want to kill the children. */
|
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;
|
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
|
#ifdef _AMIGA
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
@ -2776,9 +2793,7 @@ main (int argc, char **argv, char **envp)
|
|||||||
#endif
|
#endif
|
||||||
jobserver_post_child(1);
|
jobserver_post_child(1);
|
||||||
|
|
||||||
/* Get rid of any stdin temp file. */
|
temp_stdin_unlink ();
|
||||||
if (stdin_offset >= 0)
|
|
||||||
unlink (makefiles->list[stdin_offset]);
|
|
||||||
|
|
||||||
_exit (127);
|
_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
|
temp_stdin_unlink ();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there were no command-line goals, use the default. */
|
/* If there were no command-line goals, use the default. */
|
||||||
if (goals == 0)
|
if (goals == 0)
|
||||||
@ -3731,13 +3738,7 @@ die (int status)
|
|||||||
print_version ();
|
print_version ();
|
||||||
|
|
||||||
/* Get rid of a temp file from reading a makefile from stdin. */
|
/* Get rid of a temp file from reading a makefile from stdin. */
|
||||||
if (stdin_offset >= 0)
|
temp_stdin_unlink ();
|
||||||
{
|
|
||||||
const char *nm = makefiles->list[stdin_offset];
|
|
||||||
if (unlink (nm) < 0 && errno != ENOENT)
|
|
||||||
perror_with_name (_("unlink (temporary file): "), nm);
|
|
||||||
stdin_offset = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for children to die. */
|
/* Wait for children to die. */
|
||||||
err = (status != 0);
|
err = (status != 0);
|
||||||
|
@ -545,6 +545,7 @@ void out_of_memory () NORETURN;
|
|||||||
(_f), (_n), (_s))
|
(_f), (_n), (_s))
|
||||||
|
|
||||||
void decode_env_switches (const char*, size_t line);
|
void decode_env_switches (const char*, size_t line);
|
||||||
|
void temp_stdin_unlink (void);
|
||||||
void die (int) NORETURN;
|
void die (int) NORETURN;
|
||||||
void pfatal_with_name (const char *) NORETURN;
|
void pfatal_with_name (const char *) NORETURN;
|
||||||
void perror_with_name (const char *, const char *);
|
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);
|
'-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.
|
# This tells the test driver that the perl test script executed properly.
|
||||||
1;
|
1;
|
||||||
|
@ -46,6 +46,35 @@ force:
|
|||||||
'-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$temppath\E/");
|
'-R --debug=b -f-', "/Re-executing.+?--temp-stdin=\Q$temppath\E/");
|
||||||
|
|
||||||
if ($port_type eq 'UNIX') {
|
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.
|
# sv 62118,62145.
|
||||||
# Test that a stdin temp file is removed, when execvp fails to re-exec make.
|
# 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
|
# In order to cause execvp to fail, copy the tested make binary to the temp
|
||||||
|
Loading…
Reference in New Issue
Block a user