summaryrefslogtreecommitdiff
path: root/src/function.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2018-08-04 12:18:39 -0400
committerPaul Smith <psmith@gnu.org>2018-08-04 12:18:39 -0400
commit3112c8799358cb5d051e0b63d0e916357169942c (patch)
tree902ed1b82a9e4ab431104c96c2cdb07f2c6cfed5 /src/function.c
parent8bde7db16fa4e51239ece8a83420c580938bda24 (diff)
downloadmake-git-3112c8799358cb5d051e0b63d0e916357169942c.tar.gz
Queue failed fork() (etc.) to be handled like any other failed job.
If we failed to fork() we were essentially exiting make immediately without respect to ignore flags, etc. On one hand that makes sense because if you can't fork you're in real trouble, but it doesn't work so well on systems where we don't fork at all. Instead, treat a fork error like any other error by delaying the handling until the next call to reap_children(). Any child with a PID of -1 is considered to have died before starting so check these first without waiting for them. * src/commands.c (fatal_error_signal): Don't kill children that never started. * src/function.c (func_shell_base): Handle cleanup properly if the child doesn't start. * src/job.c (reap_children): Check for children that died before starting and handle them without waiting for the PID. (start_job_command): Free memory when the child doesn't start. (start_waiting_job): Don't manage children who never started. (child_execute_job): If the fork fails return PID -1. * src/vmsjobs.c: Check for children that never started. * tests/run_make_tests.pl: Parse config.status to get all options.
Diffstat (limited to 'src/function.c')
-rw-r--r--src/function.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/src/function.c b/src/function.c
index 2b3a5386..12e0ef2f 100644
--- a/src/function.c
+++ b/src/function.c
@@ -1698,7 +1698,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
#ifdef __MSDOS__
FILE *fpipe;
#endif
- char **command_argv;
+ char **command_argv = NULL;
const char *error_prefix;
char **envp;
int pipedes[2];
@@ -1761,7 +1761,8 @@ func_shell_base (char *o, char **argv, int trim_newlines)
if (pipedes[0] < 0)
{
perror_with_name (error_prefix, "pipe");
- return o;
+ pid = -1;
+ goto done;
}
#elif defined(WINDOWS32)
@@ -1774,14 +1775,16 @@ func_shell_base (char *o, char **argv, int trim_newlines)
/* Open of the pipe failed, mark as failed execution. */
shell_completed (127, 0);
perror_with_name (error_prefix, "pipe");
- return o;
+ pid = -1;
+ goto done;
}
#else
if (pipe (pipedes) < 0)
{
perror_with_name (error_prefix, "pipe");
- return o;
+ pid = -1;
+ goto done;
}
/* Close handles that are unnecessary for the child process. */
@@ -1798,10 +1801,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
}
if (pid < 0)
- {
- perror_with_name (error_prefix, "fork");
- return o;
- }
+ goto done;
#endif
{
@@ -1814,10 +1814,6 @@ func_shell_base (char *o, char **argv, int trim_newlines)
#ifndef __MSDOS__
shell_function_completed = 0;
- /* Free the storage only the child needed. */
- free (command_argv[0]);
- free (command_argv);
-
/* Close the write side of the pipe. We test for -1, since
pipedes[1] is -1 on MS-Windows, and some versions of MS
libraries barf when 'close' is called with -1. */
@@ -1892,6 +1888,14 @@ func_shell_base (char *o, char **argv, int trim_newlines)
free (buffer);
}
+ done:
+ if (command_argv)
+ {
+ /* Free the storage only the child needed. */
+ free (command_argv[0]);
+ free (command_argv);
+ }
+
return o;
}