VirtualBox

source: kBuild/trunk/src/kmk/output.c@ 3432

Last change on this file since 3432 was 3432, checked in by bird, 5 years ago

kmk: Quick output hack to repeat the failure output at the end of die() as it may easily get lost in output from other jobs (problem on systems with lots of cores).

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette