source: trunk/src/kmk/output.c@ 3191

Last change on this file since 3191 was 3191, checked in by bird, 7 years ago

kmk/output: Memory buffering fixes.

  • Property svn:eol-style set to native
File size: 31.2 KB
Line 
1/* Output to stdout / stderr for GNU make
2Copyright (C) 2013-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18#include "job.h"
19
20/* GNU make no longer supports pre-ANSI89 environments. */
21
22#include <assert.h>
23#include <stdio.h>
24#include <stdarg.h>
25
26#ifdef HAVE_UNISTD_H
27# include <unistd.h>
28#endif
29
30#ifdef HAVE_FCNTL_H
31# include <fcntl.h>
32#else
33# include <sys/file.h>
34#endif
35
36#ifdef WINDOWS32
37# include <windows.h>
38# include <io.h>
39# ifndef CONFIG_NEW_WIN_CHILDREN
40# include "sub_proc.h"
41# else
42# include "w32/winchildren.h"
43# endif
44#endif /* WINDOWS32 */
45#ifdef KBUILD_OS_WINDOWS
46# include "console.h"
47#endif
48
49struct output *output_context = NULL;
50unsigned int stdio_traced = 0;
51
52#define OUTPUT_NONE (-1)
53
54#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
55
56#ifdef HAVE_FCNTL_H
57# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
58#else
59# define STREAM_OK(_s) 1
60#endif
61
62
63#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
64# define MEMBUF_MIN_SEG_SIZE 4096
65# define MEMBUF_MAX_SEG_SIZE (512*1024)
66# define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \
67 - offsetof (struct output_segment, runs) \
68 - sizeof (struct output_run))
69# define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \
70 ? (size_t)512*1024 : (size_t)16*1024*1024 )
71
72static void *acquire_semaphore (void);
73static void release_semaphore (void *);
74static int log_working_directory (int);
75
76/* Is make's stdout going to the same place as stderr?
77 Also, did we already sync_init (== -1)? */
78static int combined_output = -1;
79
80/* Internal worker for output_dump and membuf_dump_most. */
81static void membuf_dump (struct output *out)
82{
83 if (out->out.total || out->err.total)
84 {
85 int traced = 0;
86 struct output_run *err_run;
87 struct output_run *out_run;
88 struct output_segment *seg;
89 FILE *prevdst;
90
91 /* Try to acquire the semaphore. If it fails, dump the output
92 unsynchronized; still better than silently discarding it.
93 We want to keep this lock for as little time as possible. */
94 void *sem = acquire_semaphore ();
95
96 /* Log the working directory for this dump. */
97 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
98 traced = log_working_directory (1);
99
100 /* Work the out and err sequences in parallel. */
101 out_run = out->out.head_run;
102 err_run = out->err.head_run;
103 prevdst = NULL;
104 while (err_run || out_run)
105 {
106 FILE *dst;
107 const void *src;
108 size_t len;
109 if (out_run && (!err_run || out_run->seqno <= err_run->seqno))
110 {
111 src = out_run + 1;
112 len = out_run->len;
113 dst = stdout;
114 out_run = out_run->next;
115 }
116 else
117 {
118 src = err_run + 1;
119 len = err_run->len;
120 dst = stderr;
121 err_run = err_run->next;
122 }
123 if (dst != prevdst)
124 fflush(prevdst);
125 prevdst = dst;
126#ifdef KBUILD_OS_WINDOWS
127 maybe_con_fwrite (src, len, 1, dst);
128#else
129 fwrite (src, len, 1, dst);
130#endif
131 }
132 if (prevdst)
133 fflush (prevdst);
134
135 if (traced)
136 log_working_directory (0);
137
138 /* Exit the critical section. */
139 if (sem)
140 release_semaphore (sem);
141
142 /* Free the segments and reset the state. */
143 while ((seg = out->out.head_seg))
144 {
145 out->out.head_seg = seg->next;
146 free (seg);
147 }
148 out->out.tail_seg = NULL;
149 out->out.tail_run = NULL;
150 out->out.head_run = NULL;
151 out->out.left = 0;
152 out->out.total = 0;
153
154 while ((seg = out->err.head_seg))
155 {
156 out->err.head_seg = seg->next;
157 free (seg);
158 }
159 out->err.tail_seg = NULL;
160 out->err.tail_run = NULL;
161 out->err.head_run = NULL;
162 out->err.left = 0;
163 out->err.total = 0;
164
165 out->seqno = 0;
166 }
167 else
168 assert (out->out.head_seg == NULL && out->err.head_seg == NULL);
169}
170
171/* Writes up to LEN bytes to the given segment.
172 Returns how much was actually written. */
173static size_t
174membuf_write_segment (struct output_membuf *membuf, struct output_segment *seg,
175 const char *src, size_t len, unsigned int *pseqno)
176{
177 size_t written = 0;
178 if (seg && membuf->left > 0)
179 {
180 struct output_run *run = membuf->tail_run;
181 char *dst = (char *)(run + 1) + run->len;
182 assert ((uintptr_t)run - (uintptr_t)seg < seg->size);
183
184 /* If the sequence number didn't change, then we can append
185 to the current run without further considerations. */
186 if (run->seqno == *pseqno)
187 written = len;
188 /* If the current run does not end with a newline, don't start a new
189 run till we encounter one. */
190 else if (dst[-1] != '\n')
191 {
192 char const *srcnl = (const char *)memchr (src, '\n', len);
193 written = srcnl ? srcnl - src + 1 : len;
194 }
195 /* Try create a new empty run and append to it. */
196 else
197 {
198 size_t const offnextrun = ( (uintptr_t)dst - (uintptr_t)(seg)
199 + sizeof(void *) - 1)
200 & ~(sizeof(void *) - 1);
201 if (offnextrun > seg->size - sizeof (struct output_run) * 2)
202 return 0; /* need new segment */
203
204 run = run->next = (struct output_run *)((char *)seg + offnextrun);
205 run->next = NULL;
206 run->seqno = ++(*pseqno);
207 run->len = 0;
208 membuf->tail_run = run;
209 membuf->left = seg->size - (offnextrun + sizeof (*run));
210 dst = (char *)(run + 1);
211 written = len;
212 }
213
214 /* Append to the current run. */
215 if (written > membuf->left)
216 written = membuf->left;
217 memcpy (dst, src, written);
218 run->len += written;
219 membuf->left -= written;
220 }
221 return written;
222}
223
224/* Helper for membuf_write_new_segment and membuf_dump_most that figures out
225 now much data needs to be moved from the previous run in order to make it
226 end with a newline. */
227static size_t membuf_calc_move_len (struct output_run *tail_run)
228{
229 size_t to_move = 0;
230 if (tail_run)
231 {
232 const char *data = (const char *)(tail_run + 1);
233 size_t off = tail_run->len;
234 while (off > 0 && data[off - 1] != '\n')
235 off--;
236 to_move = tail_run->len - off;
237 if (to_move >= MEMBUF_MAX_MOVE_LEN)
238 to_move = 0;
239 }
240 return to_move;
241}
242
243/* Allocates a new segment and writes to it.
244 This will take care to make sure the previous run terminates with
245 a newline so that we pass whole lines to fwrite when dumping. */
246static size_t
247membuf_write_new_segment (struct output_membuf *membuf, const char *src,
248 size_t len, unsigned int *pseqno)
249{
250 struct output_run *prev_run = membuf->tail_run;
251 struct output_segment *prev_seg = membuf->tail_seg;
252 size_t const to_move = membuf_calc_move_len (prev_run);
253 struct output_segment *new_seg;
254 size_t written;
255 char *dst;
256
257 /* Figure the the segment size. We start with MEMBUF_MIN_SEG_SIZE and double
258 it each time till we reach MEMBUF_MAX_SEG_SIZE. */
259 size_t const offset_runs = offsetof (struct output_segment, runs);
260 size_t segsize = !prev_seg ? MEMBUF_MIN_SEG_SIZE
261 : prev_seg->size >= MEMBUF_MAX_SEG_SIZE ? MEMBUF_MAX_SEG_SIZE
262 : prev_seg->size * 2;
263 while ( segsize < to_move + len + offset_runs + sizeof (struct output_run) * 2
264 && segsize < MEMBUF_MAX_SEG_SIZE)
265 segsize *= 2;
266
267 /* Allocate the segment and link it and the first run. */
268 new_seg = (struct output_segment *)xmalloc (segsize);
269 new_seg->size = segsize;
270 new_seg->next = NULL;
271 new_seg->runs[0].next = NULL;
272 if (!prev_seg)
273 {
274 membuf->head_seg = new_seg;
275 membuf->head_run = &new_seg->runs[0];
276 }
277 else
278 {
279 prev_seg->next = new_seg;
280 prev_run->next = &new_seg->runs[0];
281 }
282 membuf->tail_seg = new_seg;
283 membuf->tail_run = &new_seg->runs[0];
284 membuf->total += segsize;
285 membuf->left = segsize - sizeof (struct output_run) - offset_runs;
286
287 /* Initialize and write data to the first run. */
288 dst = (char *)&new_seg->runs[0]; /* Try bypass gcc array size cleverness. */
289 dst += sizeof (struct output_run);
290 assert (MEMBUF_MAX_MOVE_LEN < MEMBUF_MIN_SEG_SIZE);
291 if (to_move > 0)
292 {
293 /* Move to_move bytes from the previous run in hope that we'll get a
294 newline to soon. Afterwards call membuf_segment_write to work SRC. */
295 assert (prev_run != NULL);
296 assert (membuf->left >= to_move);
297 prev_run->len -= to_move;
298 new_seg->runs[0].len = to_move;
299 new_seg->runs[0].seqno = prev_run->seqno;
300 memcpy (dst, (const char *)(prev_run + 1) + prev_run->len, to_move);
301 membuf->left -= to_move;
302
303 written = membuf_write_segment (membuf, new_seg, src, len, pseqno);
304 }
305 else
306 {
307 /* Create a run with up to LEN from SRC. */
308 written = len;
309 if (written > membuf->left)
310 written = membuf->left;
311 new_seg->runs[0].len = written;
312 new_seg->runs[0].seqno = ++(*pseqno);
313 memcpy (dst, src, written);
314 membuf->left -= written;
315 }
316 return written;
317}
318
319/* Worker for output_write that will dump most of the output when we hit
320 MEMBUF_MAX_TOTAL on either of the two membuf structures, then free all the
321 output segments. Incomplete lines will be held over to the next buffers
322 and copied into new segments. */
323static void
324membuf_dump_most (struct output *out)
325{
326 size_t out_to_move = membuf_calc_move_len (out->out.tail_run);
327 size_t err_to_move = membuf_calc_move_len (out->err.tail_run);
328 if (!out_to_move && !err_to_move)
329 membuf_dump (out);
330 else
331 {
332 /* Allocate a stack buffer for holding incomplete lines. This should be
333 fine since we're only talking about max 2 * MEMBUF_MAX_MOVE_LEN.
334 The -1 on the sequence numbers, ise because membuf_write_new_segment
335 will increment them before use. */
336 unsigned int out_seqno = out_to_move ? out->out.tail_run->seqno - 1 : 0;
337 unsigned int err_seqno = err_to_move ? out->err.tail_run->seqno - 1 : 0;
338 char *tmp = alloca (out_to_move + err_to_move);
339 if (out_to_move)
340 {
341 out->out.tail_run->len -= out_to_move;
342 memcpy (tmp,
343 (char *)(out->out.tail_run + 1) + out->out.tail_run->len,
344 out_to_move);
345 }
346 if (err_to_move)
347 {
348 out->err.tail_run->len -= err_to_move;
349 memcpy (tmp + out_to_move,
350 (char *)(out->err.tail_run + 1) + out->err.tail_run->len,
351 err_to_move);
352 }
353
354 membuf_dump (out);
355
356 if (out_to_move)
357 {
358 size_t written = membuf_write_new_segment (&out->out, tmp,
359 out_to_move, &out_seqno);
360 assert (written == out_to_move); (void)written;
361 }
362 if (err_to_move)
363 {
364 size_t written = membuf_write_new_segment (&out->err,
365 tmp + out_to_move,
366 err_to_move, &err_seqno);
367 assert (written == err_to_move); (void)written;
368 }
369 }
370}
371
372
373
374/* write/fwrite like function, binary mode. */
375void
376output_write_bin (struct output *out, int is_err, const char *src, size_t len)
377{
378 if (!out || !out->syncout)
379 {
380 FILE *f = is_err ? stderr : stdout;
381# ifdef KBUILD_OS_WINDOWS
382 /* On windows we need to disable \n -> \r\n convers that is common on
383 standard output/error. Also optimize for console output. */
384 int fd = fileno (f);
385 int prev_mode = _setmode (fd, _O_BINARY);
386 maybe_con_fwrite (src, len, 1, f);
387 fflush (f);
388 _setmode (fd, prev_mode);
389# else
390 fwrite (src, len, 1, f);
391 fflush (f);
392# endif
393 }
394 else
395 {
396 struct output_membuf *membuf = is_err ? &out->err : &out->out;
397 while (len > 0)
398 {
399 size_t runlen = membuf_write_segment (membuf, membuf->tail_seg, src, len, &out->seqno);
400 if (!runlen)
401 {
402 if (membuf->total < MEMBUF_MAX_TOTAL)
403 runlen = membuf_write_new_segment (membuf, src, len, &out->seqno);
404 else
405 membuf_dump_most (out);
406 }
407 /* advance */
408 len -= runlen;
409 src += runlen;
410 }
411 }
412}
413
414/* write/fwrite like function, text mode. */
415void
416output_write_text (struct output *out, int is_err, const char *src, size_t len)
417{
418# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
419 if (out && out->syncout)
420 {
421 /* ASSUME fwrite does the desired conversion. */
422 FILE *f = is_err ? stderr : stdout;
423# ifdef KBUILD_OS_WINDOWS
424 maybe_con_fwrite (src, len, 1, f);
425# else
426 fwrite (src, len, 1, f);
427# endif
428 fflush (f);
429 }
430 else
431 {
432 /* Work the buffer line by line, replacing each \n with \r\n. */
433 while (len > 0)
434 {
435 const char *nl = memchr ( src, '\n', len);
436 size_t line_len = nl ? nl - src : len;
437 output_write_bin (out, is_err, src, line_len);
438 if (!nl)
439 break;
440 output_write_bin (out, is_err, "\r\n", 2);
441 len -= line_len + 1;
442 src += line_len + 1;
443 }
444 }
445# else
446 output_write_bin (out, is_err, src, len);
447# endif
448}
449
450#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
451
452
453/* Write a string to the current STDOUT or STDERR. */
454static void
455_outputs (struct output *out, int is_err, const char *msg)
456{
457#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
458 output_write_text (out, is_err, msg, strlen (msg));
459#else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
460 if (! out || ! out->syncout)
461 {
462 FILE *f = is_err ? stderr : stdout;
463# ifdef KBUILD_OS_WINDOWS
464 maybe_con_fwrite(msg, strlen(msg), 1, f);
465# else
466 fputs (msg, f);
467# endif
468 fflush (f);
469 }
470 else
471 {
472 int fd = is_err ? out->err : out->out;
473 int len = strlen (msg);
474 int r;
475
476 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
477 while (1)
478 {
479 EINTRLOOP (r, write (fd, msg, len));
480 if (r == len || r <= 0)
481 break;
482 len -= r;
483 msg += r;
484 }
485 }
486#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
487}
488
489
490/* Write a message indicating that we've just entered or
491 left (according to ENTERING) the current directory. */
492
493static int
494log_working_directory (int entering)
495{
496 static char *buf = NULL;
497 static unsigned int len = 0;
498 unsigned int need;
499 const char *fmt;
500 char *p;
501
502 /* Get enough space for the longest possible output. */
503 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
504 if (starting_directory)
505 need += strlen (starting_directory);
506
507 /* Use entire sentences to give the translators a fighting chance. */
508 if (makelevel == 0)
509 if (starting_directory == 0)
510 if (entering)
511 fmt = _("%s: Entering an unknown directory\n");
512 else
513 fmt = _("%s: Leaving an unknown directory\n");
514 else
515 if (entering)
516 fmt = _("%s: Entering directory '%s'\n");
517 else
518 fmt = _("%s: Leaving directory '%s'\n");
519 else
520 if (starting_directory == 0)
521 if (entering)
522 fmt = _("%s[%u]: Entering an unknown directory\n");
523 else
524 fmt = _("%s[%u]: Leaving an unknown directory\n");
525 else
526 if (entering)
527 fmt = _("%s[%u]: Entering directory '%s'\n");
528 else
529 fmt = _("%s[%u]: Leaving directory '%s'\n");
530
531 need += strlen (fmt);
532
533 if (need > len)
534 {
535 buf = xrealloc (buf, need);
536 len = need;
537 }
538
539 p = buf;
540 if (print_data_base_flag)
541 {
542 *(p++) = '#';
543 *(p++) = ' ';
544 }
545
546 if (makelevel == 0)
547 if (starting_directory == 0)
548 sprintf (p, fmt , program);
549 else
550 sprintf (p, fmt, program, starting_directory);
551 else if (starting_directory == 0)
552 sprintf (p, fmt, program, makelevel);
553 else
554 sprintf (p, fmt, program, makelevel, starting_directory);
555
556 _outputs (NULL, 0, buf);
557
558 return 1;
559}
560
561/* Set a file descriptor to be in O_APPEND mode.
562 If it fails, just ignore it. */
563
564static void
565set_append_mode (int fd)
566{
567#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
568 int flags = fcntl (fd, F_GETFL, 0);
569 if (flags >= 0)
570 fcntl (fd, F_SETFL, flags | O_APPEND);
571#endif
572}
573
574
575
576#ifndef NO_OUTPUT_SYNC
577
578/* Semaphore for use in -j mode with output_sync. */
579static sync_handle_t sync_handle = -1;
580
581#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
582
583/* Set up the sync handle. Disables output_sync on error. */
584static int
585sync_init (void)
586{
587 int combined_output = 0;
588
589#ifdef WINDOWS32
590 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
591 || (sync_handle = create_mutex ()) == -1)
592 {
593 perror_with_name ("output-sync suppressed: ", "stderr");
594 output_sync = 0;
595 }
596 else
597 {
598 combined_output = same_stream (stdout, stderr);
599 prepare_mutex_handle_string (sync_handle);
600 }
601
602#else
603 if (STREAM_OK (stdout))
604 {
605 struct stat stbuf_o, stbuf_e;
606
607 sync_handle = fileno (stdout);
608 combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
609 && fstat (fileno (stderr), &stbuf_e) == 0
610 && stbuf_o.st_dev == stbuf_e.st_dev
611 && stbuf_o.st_ino == stbuf_e.st_ino);
612 }
613 else if (STREAM_OK (stderr))
614 sync_handle = fileno (stderr);
615 else
616 {
617 perror_with_name ("output-sync suppressed: ", "stderr");
618 output_sync = 0;
619 }
620#endif
621
622 return combined_output;
623}
624
625#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
626/* Support routine for output_sync() */
627static void
628pump_from_tmp (int from, FILE *to)
629{
630# ifdef KMK
631 char buffer[8192];
632# else
633 static char buffer[8192];
634#endif
635
636#ifdef WINDOWS32
637 int prev_mode;
638
639 /* "from" is opened by open_tmpfd, which does it in binary mode, so
640 we need the mode of "to" to match that. */
641 prev_mode = _setmode (fileno (to), _O_BINARY);
642#endif
643
644 if (lseek (from, 0, SEEK_SET) == -1)
645 perror ("lseek()");
646
647 while (1)
648 {
649 int len;
650 EINTRLOOP (len, read (from, buffer, sizeof (buffer)));
651 if (len < 0)
652 perror ("read()");
653 if (len <= 0)
654 break;
655 if (fwrite (buffer, len, 1, to) < 1)
656 {
657 perror ("fwrite()");
658 break;
659 }
660 fflush (to);
661 }
662
663#ifdef WINDOWS32
664 /* Switch "to" back to its original mode, so that log messages by
665 Make have the same EOL format as without --output-sync. */
666 _setmode (fileno (to), prev_mode);
667#endif
668}
669#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
670
671/* Obtain the lock for writing output. */
672static void *
673acquire_semaphore (void)
674{
675 static struct flock fl;
676
677 fl.l_type = F_WRLCK;
678 fl.l_whence = SEEK_SET;
679 fl.l_start = 0;
680 fl.l_len = 1;
681 if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
682 return &fl;
683 perror ("fcntl()");
684 return NULL;
685}
686
687/* Release the lock for writing output. */
688static void
689release_semaphore (void *sem)
690{
691 struct flock *flp = (struct flock *)sem;
692 flp->l_type = F_UNLCK;
693 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
694 perror ("fcntl()");
695}
696
697#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
698
699/* Returns a file descriptor to a temporary file. The file is automatically
700 closed/deleted on exit. Don't use a FILE* stream. */
701int
702output_tmpfd (void)
703{
704 int fd = -1;
705 FILE *tfile = tmpfile ();
706
707 if (! tfile)
708 pfatal_with_name ("tmpfile");
709
710 /* Create a duplicate so we can close the stream. */
711 fd = dup (fileno (tfile));
712 if (fd < 0)
713 pfatal_with_name ("dup");
714
715 fclose (tfile);
716
717 set_append_mode (fd);
718
719 return fd;
720}
721
722/* Adds file descriptors to the child structure to support output_sync; one
723 for stdout and one for stderr as long as they are open. If stdout and
724 stderr share a device they can share a temp file too.
725 Will reset output_sync on error. */
726static void
727setup_tmpfile (struct output *out)
728{
729 /* Is make's stdout going to the same place as stderr? */
730 static int combined_output = -1;
731
732 if (combined_output < 0)
733 combined_output = sync_init ();
734
735 if (STREAM_OK (stdout))
736 {
737 int fd = output_tmpfd ();
738 if (fd < 0)
739 goto error;
740 CLOSE_ON_EXEC (fd);
741 out->out = fd;
742 }
743
744 if (STREAM_OK (stderr))
745 {
746 if (out->out != OUTPUT_NONE && combined_output)
747 out->err = out->out;
748 else
749 {
750 int fd = output_tmpfd ();
751 if (fd < 0)
752 goto error;
753 CLOSE_ON_EXEC (fd);
754 out->err = fd;
755 }
756 }
757
758 return;
759
760 /* If we failed to create a temp file, disable output sync going forward. */
761 error:
762 output_close (out);
763 output_sync = OUTPUT_SYNC_NONE;
764}
765
766#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
767
768/* Synchronize the output of jobs in -j mode to keep the results of
769 each job together. This is done by holding the results in temp files,
770 one for stdout and potentially another for stderr, and only releasing
771 them to "real" stdout/stderr when a semaphore can be obtained. */
772
773void
774output_dump (struct output *out)
775{
776#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
777 membuf_dump (out);
778#else
779 int outfd_not_empty = FD_NOT_EMPTY (out->out);
780 int errfd_not_empty = FD_NOT_EMPTY (out->err);
781
782 if (outfd_not_empty || errfd_not_empty)
783 {
784 int traced = 0;
785
786 /* Try to acquire the semaphore. If it fails, dump the output
787 unsynchronized; still better than silently discarding it.
788 We want to keep this lock for as little time as possible. */
789 void *sem = acquire_semaphore ();
790
791 /* Log the working directory for this dump. */
792 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
793 traced = log_working_directory (1);
794
795 if (outfd_not_empty)
796 pump_from_tmp (out->out, stdout);
797 if (errfd_not_empty && out->err != out->out)
798 pump_from_tmp (out->err, stderr);
799
800 if (traced)
801 log_working_directory (0);
802
803 /* Exit the critical section. */
804 if (sem)
805 release_semaphore (sem);
806
807 /* Truncate and reset the output, in case we use it again. */
808 if (out->out != OUTPUT_NONE)
809 {
810 int e;
811 lseek (out->out, 0, SEEK_SET);
812 EINTRLOOP (e, ftruncate (out->out, 0));
813 }
814 if (out->err != OUTPUT_NONE && out->err != out->out)
815 {
816 int e;
817 lseek (out->err, 0, SEEK_SET);
818 EINTRLOOP (e, ftruncate (out->err, 0));
819 }
820 }
821#endif
822}
823#endif /* NO_OUTPUT_SYNC */
824
825
826
827/* Provide support for temporary files. */
828
829#ifndef HAVE_STDLIB_H
830# ifdef HAVE_MKSTEMP
831int mkstemp (char *template);
832# else
833char *mktemp (char *template);
834# endif
835#endif
836
837FILE *
838output_tmpfile (char **name, const char *template)
839{
840#ifdef HAVE_FDOPEN
841 int fd;
842#endif
843
844#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
845# define TEMPLATE_LEN strlen (template)
846#else
847# define TEMPLATE_LEN L_tmpnam
848#endif
849 *name = xmalloc (TEMPLATE_LEN + 1);
850 strcpy (*name, template);
851
852#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
853 /* It's safest to use mkstemp(), if we can. */
854 fd = mkstemp (*name);
855 if (fd == -1)
856 return 0;
857 return fdopen (fd, "w");
858#else
859# ifdef HAVE_MKTEMP
860 (void) mktemp (*name);
861# else
862 (void) tmpnam (*name);
863# endif
864
865# ifdef HAVE_FDOPEN
866 /* Can't use mkstemp(), but guard against a race condition. */
867 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
868 if (fd == -1)
869 return 0;
870 return fdopen (fd, "w");
871# else
872 /* Not secure, but what can we do? */
873 return fopen (*name, "w");
874# endif
875#endif
876}
877
878
879
880/* This code is stolen from gnulib.
881 If/when we abandon the requirement to work with K&R compilers, we can
882 remove this (and perhaps other parts of GNU make!) and migrate to using
883 gnulib directly.
884
885 This is called only through atexit(), which means die() has already been
886 invoked. So, call exit() here directly. Apparently that works...?
887*/
888
889/* Close standard output, exiting with status 'exit_failure' on failure.
890 If a program writes *anything* to stdout, that program should close
891 stdout and make sure that it succeeds before exiting. Otherwise,
892 suppose that you go to the extreme of checking the return status
893 of every function that does an explicit write to stdout. The last
894 printf can succeed in writing to the internal stream buffer, and yet
895 the fclose(stdout) could still fail (due e.g., to a disk full error)
896 when it tries to write out that buffered data. Thus, you would be
897 left with an incomplete output file and the offending program would
898 exit successfully. Even calling fflush is not always sufficient,
899 since some file systems (NFS and CODA) buffer written/flushed data
900 until an actual close call.
901
902 Besides, it's wasteful to check the return value from every call
903 that writes to stdout -- just let the internal stream state record
904 the failure. That's what the ferror test is checking below.
905
906 It's important to detect such failures and exit nonzero because many
907 tools (most notably 'make' and other build-management systems) depend
908 on being able to detect failure in other tools via their exit status. */
909
910static void
911close_stdout (void)
912{
913 int prev_fail = ferror (stdout);
914 int fclose_fail = fclose (stdout);
915
916 if (prev_fail || fclose_fail)
917 {
918 if (fclose_fail)
919 perror_with_name (_("write error: stdout"), "");
920 else
921 O (error, NILF, _("write error: stdout"));
922 exit (MAKE_TROUBLE);
923 }
924}
925
926
927
928void
929output_init (struct output *out)
930{
931 if (out)
932 {
933#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
934 out->out.head_seg = NULL;
935 out->out.tail_seg = NULL;
936 out->out.head_run = NULL;
937 out->out.tail_run = NULL;
938 out->err.head_seg = NULL;
939 out->err.tail_seg = NULL;
940 out->err.head_run = NULL;
941 out->err.tail_run = NULL;
942 out->err.total = 0;
943 out->out.total = 0;
944 out->seqno = 0;
945#else
946 out->out = out->err = OUTPUT_NONE;
947#endif
948 out->syncout = !!output_sync;
949 return;
950 }
951
952 /* Configure this instance of make. Be sure stdout is line-buffered. */
953
954#ifdef HAVE_SETVBUF
955# ifdef SETVBUF_REVERSED
956 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
957# else /* setvbuf not reversed. */
958 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
959 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
960# endif /* setvbuf reversed. */
961#elif HAVE_SETLINEBUF
962 setlinebuf (stdout);
963#endif /* setlinebuf missing. */
964
965 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
966 lose output due to overlapping writes. */
967 set_append_mode (fileno (stdout));
968 set_append_mode (fileno (stderr));
969
970#ifdef HAVE_ATEXIT
971 if (STREAM_OK (stdout))
972 atexit (close_stdout);
973#endif
974}
975
976void
977output_close (struct output *out)
978{
979 if (! out)
980 {
981 if (stdio_traced)
982 log_working_directory (0);
983 return;
984 }
985
986#ifndef NO_OUTPUT_SYNC
987 output_dump (out);
988#endif
989
990#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
991 assert (out->out.total == 0);
992 assert (out->out.head_seg == NULL);
993 assert (out->err.total == 0);
994 assert (out->err.head_seg == NULL);
995#else
996 if (out->out >= 0)
997 close (out->out);
998 if (out->err >= 0 && out->err != out->out)
999 close (out->err);
1000#endif
1001
1002 output_init (out);
1003}
1004
1005/* We're about to generate output: be sure it's set up. */
1006void
1007output_start (void)
1008{
1009#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1010 /* If we're syncing output make sure the sempahore (win) is set up. */
1011 if (output_context && output_context->syncout)
1012 if (combined_output < 0)
1013 combined_output = sync_init ();
1014#else
1015#ifndef NO_OUTPUT_SYNC
1016 /* If we're syncing output make sure the temporary file is set up. */
1017 if (output_context && output_context->syncout)
1018 if (! OUTPUT_ISSET(output_context))
1019 setup_tmpfile (output_context);
1020#endif
1021#endif
1022
1023 /* If we're not syncing this output per-line or per-target, make sure we emit
1024 the "Entering..." message where appropriate. */
1025 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1026 if (! stdio_traced && print_directory_flag)
1027 stdio_traced = log_working_directory (1);
1028}
1029
1030void
1031outputs (int is_err, const char *msg)
1032{
1033 if (! msg || *msg == '\0')
1034 return;
1035
1036 output_start ();
1037
1038 _outputs (output_context, is_err, msg);
1039}
1040
1041
1042
1043static struct fmtstring
1044 {
1045 char *buffer;
1046 size_t size;
1047 } fmtbuf = { NULL, 0 };
1048
1049static char *
1050get_buffer (size_t need)
1051{
1052 /* Make sure we have room. NEED includes space for \0. */
1053 if (need > fmtbuf.size)
1054 {
1055 fmtbuf.size += need * 2;
1056 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1057 }
1058
1059 fmtbuf.buffer[need-1] = '\0';
1060
1061 return fmtbuf.buffer;
1062}
1063
1064/* Print a message on stdout. */
1065
1066void
1067message (int prefix, size_t len, const char *fmt, ...)
1068{
1069 va_list args;
1070 char *p;
1071
1072 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1073 p = get_buffer (len);
1074
1075 if (prefix)
1076 {
1077 if (makelevel == 0)
1078 sprintf (p, "%s: ", program);
1079 else
1080 sprintf (p, "%s[%u]: ", program, makelevel);
1081 p += strlen (p);
1082 }
1083
1084 va_start (args, fmt);
1085 vsprintf (p, fmt, args);
1086 va_end (args);
1087
1088 strcat (p, "\n");
1089
1090 assert (fmtbuf.buffer[len-1] == '\0');
1091 outputs (0, fmtbuf.buffer);
1092}
1093
1094/* Print an error message. */
1095
1096void
1097error (const floc *flocp, size_t len, const char *fmt, ...)
1098{
1099 va_list args;
1100 char *p;
1101
1102 len += (strlen (fmt) + strlen (program)
1103 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1104 + INTSTR_LENGTH + 4 + 1 + 1);
1105 p = get_buffer (len);
1106
1107 if (flocp && flocp->filenm)
1108 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1109 else if (makelevel == 0)
1110 sprintf (p, "%s: ", program);
1111 else
1112 sprintf (p, "%s[%u]: ", program, makelevel);
1113 p += strlen (p);
1114
1115 va_start (args, fmt);
1116 vsprintf (p, fmt, args);
1117 va_end (args);
1118
1119 strcat (p, "\n");
1120
1121 assert (fmtbuf.buffer[len-1] == '\0');
1122 outputs (1, fmtbuf.buffer);
1123}
1124
1125/* Print an error message and exit. */
1126
1127void
1128fatal (const floc *flocp, size_t len, const char *fmt, ...)
1129{
1130 va_list args;
1131 const char *stop = _(". Stop.\n");
1132 char *p;
1133
1134 len += (strlen (fmt) + strlen (program)
1135 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1136 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1137 p = get_buffer (len);
1138
1139 if (flocp && flocp->filenm)
1140 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1141 else if (makelevel == 0)
1142 sprintf (p, "%s: *** ", program);
1143 else
1144 sprintf (p, "%s[%u]: *** ", program, makelevel);
1145 p += strlen (p);
1146
1147 va_start (args, fmt);
1148 vsprintf (p, fmt, args);
1149 va_end (args);
1150
1151 strcat (p, stop);
1152
1153 assert (fmtbuf.buffer[len-1] == '\0');
1154 outputs (1, fmtbuf.buffer);
1155
1156 die (MAKE_FAILURE);
1157}
1158
1159/* Print an error message from errno. */
1160
1161void
1162perror_with_name (const char *str, const char *name)
1163{
1164 const char *err = strerror (errno);
1165 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1166}
1167
1168/* Print an error message from errno and exit. */
1169
1170void
1171pfatal_with_name (const char *name)
1172{
1173 const char *err = strerror (errno);
1174 OSS (fatal, NILF, _("%s: %s"), name, err);
1175
1176 /* NOTREACHED */
1177}
Note: See TracBrowser for help on using the repository browser.