summaryrefslogtreecommitdiff
path: root/function.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2016-03-13 01:12:07 -0500
committerPaul Smith <psmith@gnu.org>2016-03-13 01:12:07 -0500
commitfd1dd7c398974b05950735a724838c09eb72ad1e (patch)
tree3ab124b56dfb7eb29597fcbb9b4393ad960143fb /function.c
parent14b2d7effb0afd75dfd1ed2534e331784f7d2977 (diff)
[SV 44555] Use vfork() instead of fork() where available.
Testing has shown that vfork() is actually significantly more efficient on systems where it's supported, even for copy-on-write implementations. If make is big enough, duplicating the page tables is significant overhead. * configure.ac: Check for fork/vfork. * makeint.h: Include vfork.h and set up #define for it. * os.h, posixos.c (get_bad_stdin): For children who can't use the normal stdin file descriptor, get a broken one. * job.c (start_job_command): Avoid so many ifdefs and simplify the invocation of child_execute_job() (child_execute_job): move the fork operation here so it can return early for the parent process. Switch to use vfork(). * function.c (func_shell_base): Use new child_execute_job() and simplify ifdefs. * job.h, main.c, remote-cstms.c, vmsjobs.c, w32os.c: Update declarations and calls.
Diffstat (limited to 'function.c')
-rw-r--r--function.c174
1 files changed, 85 insertions, 89 deletions
diff --git a/function.c b/function.c
index 7dea72f2..9f9f0fc3 100644
--- a/function.c
+++ b/function.c
@@ -1751,6 +1751,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
perror_with_name (error_prefix, "pipe");
return o;
}
+
#elif defined(WINDOWS32)
windows32_openpipe (pipedes, errfd, &pid, command_argv, envp);
/* Restore the value of just_print_flag. */
@@ -1763,7 +1764,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
perror_with_name (error_prefix, "pipe");
return o;
}
- else
+
#else
if (pipe (pipedes) < 0)
{
@@ -1771,118 +1772,113 @@ func_shell_base (char *o, char **argv, int trim_newlines)
return o;
}
-# ifdef __EMX__
- /* close some handles that are unnecessary for the child process */
+ /* Close handles that are unnecessary for the child process. */
CLOSE_ON_EXEC(pipedes[1]);
CLOSE_ON_EXEC(pipedes[0]);
- /* Never use fork()/exec() here! Use spawn() instead in exec_command() */
- pid = child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
- if (pid < 0)
- perror_with_name (error_prefix, "spawn");
-# else /* ! __EMX__ */
- pid = fork ();
+
+ {
+ struct output out;
+ out.syncout = 1;
+ out.out = pipedes[1];
+ out.err = errfd;
+
+ pid = child_execute_job (&out, 1, command_argv, envp);
+ }
+
if (pid < 0)
- perror_with_name (error_prefix, "fork");
- else if (pid == 0)
{
-# ifdef SET_STACK_SIZE
- /* Reset limits, if necessary. */
- if (stack_limit.rlim_cur)
- setrlimit (RLIMIT_STACK, &stack_limit);
-# endif
- child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
+ perror_with_name (error_prefix, "fork");
+ return o;
}
- else
-# endif
#endif
- {
- /* We are the parent. */
- char *buffer;
- unsigned int maxlen, i;
- int cc;
- /* Record the PID for reap_children. */
- shell_function_pid = pid;
+ {
+ char *buffer;
+ unsigned int maxlen, i;
+ int cc;
+
+ /* Record the PID for reap_children. */
+ shell_function_pid = pid;
#ifndef __MSDOS__
- shell_function_completed = 0;
+ shell_function_completed = 0;
- /* Free the storage only the child needed. */
- free (command_argv[0]);
- free (command_argv);
+ /* 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. */
- if (pipedes[1] >= 0)
- close (pipedes[1]);
+ /* 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. */
+ if (pipedes[1] >= 0)
+ close (pipedes[1]);
#endif
- /* Set up and read from the pipe. */
+ /* Set up and read from the pipe. */
- maxlen = 200;
- buffer = xmalloc (maxlen + 1);
+ maxlen = 200;
+ buffer = xmalloc (maxlen + 1);
- /* Read from the pipe until it gets EOF. */
- for (i = 0; ; i += cc)
- {
- if (i == maxlen)
- {
- maxlen += 512;
- buffer = xrealloc (buffer, maxlen + 1);
- }
+ /* Read from the pipe until it gets EOF. */
+ for (i = 0; ; i += cc)
+ {
+ if (i == maxlen)
+ {
+ maxlen += 512;
+ buffer = xrealloc (buffer, maxlen + 1);
+ }
- EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
- if (cc <= 0)
- break;
- }
- buffer[i] = '\0';
+ EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i));
+ if (cc <= 0)
+ break;
+ }
+ buffer[i] = '\0';
- /* Close the read side of the pipe. */
+ /* Close the read side of the pipe. */
#ifdef __MSDOS__
- if (fpipe)
- {
- int st = pclose (fpipe);
- shell_completed (st, 0);
- }
+ if (fpipe)
+ {
+ int st = pclose (fpipe);
+ shell_completed (st, 0);
+ }
#else
- (void) close (pipedes[0]);
+ (void) close (pipedes[0]);
#endif
- /* Loop until child_handler or reap_children() sets
- shell_function_completed to the status of our child shell. */
- while (shell_function_completed == 0)
- reap_children (1, 0);
+ /* Loop until child_handler or reap_children() sets
+ shell_function_completed to the status of our child shell. */
+ while (shell_function_completed == 0)
+ reap_children (1, 0);
- if (batch_filename)
- {
- DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
- batch_filename));
- remove (batch_filename);
- free (batch_filename);
- }
- shell_function_pid = 0;
+ if (batch_filename)
+ {
+ DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"),
+ batch_filename));
+ remove (batch_filename);
+ free (batch_filename);
+ }
+ shell_function_pid = 0;
- /* shell_completed() will set shell_function_completed to 1 when the
- child dies normally, or to -1 if it dies with status 127, which is
- most likely an exec fail. */
+ /* shell_completed() will set shell_function_completed to 1 when the
+ child dies normally, or to -1 if it dies with status 127, which is
+ most likely an exec fail. */
- if (shell_function_completed == -1)
- {
- /* This likely means that the execvp failed, so we should just
- write the error message in the pipe from the child. */
- fputs (buffer, stderr);
- fflush (stderr);
- }
- else
- {
- /* The child finished normally. Replace all newlines in its output
- with spaces, and put that in the variable output buffer. */
- fold_newlines (buffer, &i, trim_newlines);
- o = variable_buffer_output (o, buffer, i);
- }
+ if (shell_function_completed == -1)
+ {
+ /* This likely means that the execvp failed, so we should just
+ write the error message in the pipe from the child. */
+ fputs (buffer, stderr);
+ fflush (stderr);
+ }
+ else
+ {
+ /* The child finished normally. Replace all newlines in its output
+ with spaces, and put that in the variable output buffer. */
+ fold_newlines (buffer, &i, trim_newlines);
+ o = variable_buffer_output (o, buffer, i);
+ }
- free (buffer);
- }
+ free (buffer);
+ }
return o;
}