VirtualBox

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

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

kmk,kWorker: Some fixes wrt output capture and ctrl-c.

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

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