VirtualBox

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

最後變更 在這個檔案從3211是 3211,由 bird 提交於 7 年 前

kmk/output.c: membuf_dump must set stdout+stderr to _O_BINARY while dumping buffered stuff, as it already has be subject to \n -> \r\n conversion and doesn't benefit from doing it again.

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

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