Avoid interleaved $(info ) output

Since $(info ) function output is written using two system calls for
the message and the newline, it's possible for output from another
parallel make job to sneak in between them.

Reported by Paul Eggert <eggert@cs.ucla.edu>, who saw the report from
Lars Ingebrigtsen <https://bugs.gnu.org/53358>.

* src/function.c (func_error): Paul provided a fix but instead I
rewrote the entire function: it's not possible for it to be invoked
with anything other than exactly one argument so don't worry about
re-combining the arguments.
This commit is contained in:
Paul Smith 2022-01-19 15:49:19 -08:00
parent cbe0d2e47f
commit 5f2d114c6d

View file

@ -1171,41 +1171,25 @@ func_strip (char *o, char **argv, const char *funcname UNUSED)
static char * static char *
func_error (char *o, char **argv, const char *funcname) func_error (char *o, char **argv, const char *funcname)
{ {
char **argvp;
char *msg, *p;
size_t len;
/* The arguments will be broken on commas. Rather than create yet
another special case where function arguments aren't broken up,
just create a format string that puts them back together. */
for (len=0, argvp=argv; *argvp != 0; ++argvp)
len += strlen (*argvp) + 2;
p = msg = alloca (len + 1);
msg[0] = '\0';
for (argvp=argv; argvp[1] != 0; ++argvp)
{
strcpy (p, *argvp);
p += strlen (*argvp);
*(p++) = ',';
*(p++) = ' ';
}
strcpy (p, *argvp);
switch (*funcname) switch (*funcname)
{ {
case 'e': case 'e':
OS (fatal, reading_file, "%s", msg); OS (fatal, reading_file, "%s", argv[0]);
case 'w': case 'w':
OS (error, reading_file, "%s", msg); OS (error, reading_file, "%s", argv[0]);
break; break;
case 'i': case 'i':
outputs (0, msg); {
outputs (0, "\n"); size_t len = strlen (argv[0]);
break; char *msg = alloca (len + 2);
strcpy (msg, argv[0]);
msg[len] = '\n';
msg[len + 1] = '\0';
outputs (0, msg);
break;
}
default: default:
OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname); OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname);