Final fixes for obscure output-sync errors.

This commit is contained in:
Paul Smith 2013-09-29 21:57:22 -04:00
parent 1f4ca0539b
commit 8e12202870
4 changed files with 73 additions and 63 deletions

View File

@ -1,5 +1,16 @@
2013-09-29 Paul Smith <psmith@gnu.org>
* output.c (output_dump): Always write Enter/Leave messages to stdio.
(log_working_directory): This now always writes to stdio, so we
don't need the struct output parameter anymore.
(output_start): Show the working directory when output_sync is not
set or is recursive.
* main.c (main): Ensure the special "already shown Enter message"
token is removed from MAKE_RESTARTS before the user can see it.
* function.c (func_shell_base): If the output_context stderr
exists but is invalid, write to the real stderr.
Fixes suggested by Frank Heckenbach <f.heckenbach@fh-soft.de>.
* output.c: Guard unistd.h inclusion, add io.h.
* gnumake.h: Move GMK_EXPORT before the declarations.
* make_msvc_net2003.vcproj: Add missing files.

View File

@ -1620,7 +1620,7 @@ char *
func_shell_base (char *o, char **argv, int trim_newlines)
{
char *batch_filename = NULL;
int errfd;
#ifdef __MSDOS__
FILE *fpipe;
#endif
@ -1636,9 +1636,9 @@ func_shell_base (char *o, char **argv, int trim_newlines)
are used to run the commands, because we normally refrain from
creating batch files under -n. */
int j_p_f = just_print_flag;
just_print_flag = 0;
#endif
/* Construct the argument list. */
command_argv = construct_command_argv (argv[0], NULL, NULL, 0,
&batch_filename);
@ -1655,7 +1655,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
export var = $(shell echo foobie)
bad := $(var)
because target_environment hits a loop trying to expand $(var) to put it
in the environment. This is even more confusing when var was not
in the environment. This is even more confusing when 'var' was not
explicitly exported, but just appeared in the calling environment.
See Savannah bug #10593.
@ -1678,6 +1678,9 @@ func_shell_base (char *o, char **argv, int trim_newlines)
/* Set up the output in case the shell writes something. */
output_start ();
errfd = (output_context && output_context->err >= 0
? output_context->err : FD_STDERR);
#if defined(__MSDOS__)
fpipe = msdos_openpipe (pipedes, &pid, argv[0]);
if (pipedes[0] < 0)
@ -1710,7 +1713,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
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], FD_STDERR, command_argv, envp);
pid = child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
if (pid < 0)
perror_with_name (error_prefix, "spawn");
# else /* ! __EMX__ */
@ -1724,9 +1727,7 @@ func_shell_base (char *o, char **argv, int trim_newlines)
if (stack_limit.rlim_cur)
setrlimit (RLIMIT_STACK, &stack_limit);
# endif
child_execute_job (FD_STDIN, pipedes[1],
output_context ? output_context->err : FD_STDERR,
command_argv, envp);
child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp);
}
else
# endif

80
main.c
View File

@ -1295,64 +1295,62 @@ main (int argc, char **argv, char **envp)
for (i = 0; envp[i] != 0; ++i)
{
int do_not_define = 0;
struct variable *v;
char *ep = envp[i];
/* By default, export all variables culled from the environment. */
enum variable_export export = v_export;
unsigned int len;
while (! STOP_SET (*ep, MAP_EQUALS))
++ep;
/* If there's no equals sign it's a malformed environment. Ignore. */
if (*ep == '\0')
continue;
#ifdef WINDOWS32
if (!unix_path && strneq (envp[i], "PATH=", 5))
unix_path = ep+1;
else if (!strnicmp (envp[i], "Path=", 5))
{
do_not_define = 1; /* it gets defined after loop exits */
if (!windows32_path)
windows32_path = ep+1;
/* PATH gets defined after the loop exits. */
continue;
}
#endif
/* The result of pointer arithmetic is cast to unsigned int for
machines where ptrdiff_t is a different size that doesn't widen
the same. */
if (!do_not_define)
/* Length of the variable name, and skip the '='. */
len = ep++ - envp[i];
/* If this is MAKE_RESTARTS, check to see if the "already printed
the enter statement" flag is set. */
if (len == 13 && strneq (envp[i], "MAKE_RESTARTS", 13))
{
struct variable *v;
v = define_variable (envp[i], (unsigned int) (ep - envp[i]),
ep + 1, o_env, 1);
/* Force exportation of every variable culled from the
environment. We used to rely on target_environment's
v_default code to do this. But that does not work for the
case where an environment variable is redefined in a makefile
with 'override'; it should then still be exported, because it
was originally in the environment. */
v->export = v_export;
/* Another wrinkle is that POSIX says the value of SHELL set in
the makefile won't change the value of SHELL given to
subprocesses. */
if (streq (v->name, "SHELL"))
if (*ep == '-')
{
#ifndef __MSDOS__
v->export = v_noexport;
#endif
shell_var.name = "SHELL";
shell_var.length = 5;
shell_var.value = xstrdup (ep + 1);
}
/* If MAKE_RESTARTS is set, remember it but don't export it.
If it's negative, it means the "enter" message was printed. */
else if (streq (v->name, "MAKE_RESTARTS"))
{
v->export = v_noexport;
if (*(++ep) == '-')
{
OUTPUT_TRACED ();
++ep;
}
restarts = (unsigned int) atoi (ep);
OUTPUT_TRACED ();
++ep;
}
restarts = (unsigned int) atoi (ep);
export = v_noexport;
}
v = define_variable (envp[i], len, ep, o_env, 1);
/* POSIX says the value of SHELL set in the makefile won't change the
value of SHELL given to subprocesses. */
if (streq (v->name, "SHELL"))
{
#ifndef __MSDOS__
export = v_noexport;
#endif
shell_var.name = "SHELL";
shell_var.length = 5;
shell_var.value = xstrdup (ep);
}
v->export = export;
}
}
#ifdef WINDOWS32

View File

@ -96,10 +96,8 @@ _outputs (struct output *out, int is_err, const char *msg)
while (1)
{
EINTRLOOP (r, write (fd, msg, len));
if (r == len)
if (r == len || r <= 0)
break;
if (r <= 0)
return;
len -= r;
msg += r;
}
@ -110,7 +108,7 @@ _outputs (struct output *out, int is_err, const char *msg)
left (according to ENTERING) the current directory. */
static int
log_working_directory (struct output *out, int entering)
log_working_directory (int entering)
{
static char *buf = NULL;
static unsigned int len = 0;
@ -172,7 +170,7 @@ log_working_directory (struct output *out, int entering)
else
sprintf (p, fmt, program, makelevel, starting_directory);
_outputs (out, 0, buf);
_outputs (NULL, 0, buf);
return 1;
}
@ -391,7 +389,7 @@ output_dump (struct output *out)
/* Log the working directory for this dump. */
if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
traced = log_working_directory (output_context, 1);
traced = log_working_directory (1);
if (outfd_not_empty)
pump_from_tmp (out->out, stdout);
@ -399,7 +397,7 @@ output_dump (struct output *out)
pump_from_tmp (out->err, stderr);
if (traced)
log_working_directory (output_context, 0);
log_working_directory (0);
/* Exit the critical section. */
if (sem)
@ -562,7 +560,7 @@ output_close (struct output *out)
if (! out)
{
if (stdio_traced)
log_working_directory (NULL, 0);
log_working_directory (0);
return;
}
@ -583,15 +581,17 @@ void
output_start ()
{
#ifndef NO_OUTPUT_SYNC
if (output_context && output_context->syncout && ! OUTPUT_ISSET(output_context))
setup_tmpfile (output_context);
/* If we're syncing output make sure the temporary file is set up. */
if (output_context && output_context->syncout)
if (! OUTPUT_ISSET(output_context))
setup_tmpfile (output_context);
#endif
if (! output_context || output_sync == OUTPUT_SYNC_RECURSE)
{
if (! stdio_traced && print_directory_flag)
stdio_traced = log_working_directory (NULL, 1);
}
/* If we're not syncing this output per-line or per-target, make sure we emit
the "Entering..." message where appropriate. */
if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
if (! stdio_traced && print_directory_flag)
stdio_traced = log_working_directory (1);
}
void