VirtualBox

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

Last change on this file since 3664 was 3664, checked in by bird, 2 months ago

kmk/output.c: More debugging code for the mysterious 'kmk: write error: stdout' problem...

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