VirtualBox

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

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

kmk/output.c: Attempts at dealing with infinite recursion occuring on tmpfile() or sync_init() failure.

  • Property svn:eol-style set to native
File size: 35.1 KB
Line 
1/* Output to stdout / stderr for GNU make
2Copyright (C) 2013-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18#include "job.h"
19
20/* GNU make no longer supports pre-ANSI89 environments. */
21
22#include <assert.h>
23#include <stdio.h>
24#include <stdarg.h>
25
26#ifdef HAVE_UNISTD_H
27# include <unistd.h>
28#endif
29
30#ifdef HAVE_FCNTL_H
31# include <fcntl.h>
32#else
33# include <sys/file.h>
34#endif
35
36#ifdef WINDOWS32
37# include <windows.h>
38# include <io.h>
39# ifndef CONFIG_NEW_WIN_CHILDREN
40# include "sub_proc.h"
41# else
42# include "w32/winchildren.h"
43# endif
44#endif /* WINDOWS32 */
45#ifdef KBUILD_OS_WINDOWS
46# include "console.h"
47#endif
48
49struct output *output_context = NULL;
50unsigned int stdio_traced = 0;
51
52#define OUTPUT_NONE (-1)
53
54#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
55
56#ifdef HAVE_FCNTL_H
57# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
58#else
59# define STREAM_OK(_s) 1
60#endif
61
62
63#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
64# define MEMBUF_MIN_SEG_SIZE 4096
65# define MEMBUF_MAX_SEG_SIZE (512*1024)
66# define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \
67 - offsetof (struct output_segment, runs) \
68 - sizeof (struct output_run))
69# define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \
70 ? (size_t)512*1024 : (size_t)16*1024*1024 )
71
72static void *acquire_semaphore (void);
73static void release_semaphore (void *);
74static int log_working_directory (int);
75
76/* Is make's stdout going to the same place as stderr?
77 Also, did we already sync_init (== -1)? */
78static int combined_output = -1;
79
80/* Internal worker for output_dump and membuf_dump_most. */
81static void membuf_dump (struct output *out)
82{
83 if (out->out.total || out->err.total)
84 {
85 int traced = 0;
86 struct output_run *err_run;
87 struct output_run *out_run;
88 struct output_segment *seg;
89 FILE *prevdst;
90
91 /* Try to acquire the semaphore. If it fails, dump the output
92 unsynchronized; still better than silently discarding it.
93 We want to keep this lock for as little time as possible. */
94 void *sem = acquire_semaphore ();
95# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
96 int prev_mode_out = _setmode (fileno (stdout), _O_BINARY);
97 int prev_mode_err = _setmode (fileno (stderr), _O_BINARY);
98# endif
99
100# ifndef KMK /* this drives me bananas. */
101 /* Log the working directory for this dump. */
102 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
103 traced = log_working_directory (1);
104# endif
105
106 /* Work the out and err sequences in parallel. */
107 out_run = out->out.head_run;
108 err_run = out->err.head_run;
109 prevdst = NULL;
110 while (err_run || out_run)
111 {
112 FILE *dst;
113 const void *src;
114 size_t len;
115 if (out_run && (!err_run || out_run->seqno <= err_run->seqno))
116 {
117 src = out_run + 1;
118 len = out_run->len;
119 dst = stdout;
120 out_run = out_run->next;
121 }
122 else
123 {
124 src = err_run + 1;
125 len = err_run->len;
126 dst = stderr;
127 err_run = err_run->next;
128 }
129 if (dst != prevdst)
130 fflush(prevdst);
131 prevdst = dst;
132# if 0 /* for debugging */
133 while (len > 0)
134 {
135 const char *nl = (const char *)memchr (src, '\n', len);
136 size_t line_len = nl ? nl - (const char *)src + 1 : len;
137 char *tmp = (char *)xmalloc (1 + line_len + 1 + 1);
138 tmp[0] = '{';
139 memcpy (&tmp[1], src, line_len);
140 tmp[1 + line_len] = '}';
141# ifdef KBUILD_OS_WINDOWS
142 maybe_con_fwrite (tmp, 1 + line_len + 1, 1, dst);
143# else
144 fwrite (tmp, 1 + line_len + 1, 1, dst);
145# endif
146 free (tmp);
147 src = (const char *)src + line_len;
148 len -= line_len;
149 }
150#else
151# ifdef KBUILD_OS_WINDOWS
152 maybe_con_fwrite (src, len, 1, dst);
153# else
154 fwrite (src, len, 1, dst);
155# endif
156# endif
157 }
158 if (prevdst)
159 fflush (prevdst);
160
161# ifndef KMK /* this drives me bananas. */
162 if (traced)
163 log_working_directory (0);
164# endif
165
166 /* Exit the critical section. */
167# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
168 _setmode (fileno (stdout), prev_mode_out);
169 _setmode (fileno (stderr), prev_mode_err);
170# endif
171 if (sem)
172 release_semaphore (sem);
173
174 /* 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#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
454
455/* write/fwrite like function, text mode. */
456ssize_t
457output_write_text (struct output *out, int is_err, const char *src, size_t len)
458{
459#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
460# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
461 ssize_t ret = len;
462 if (!out || !out->syncout)
463 {
464 /* ASSUME fwrite does the desired conversion. */
465 FILE *f = is_err ? stderr : stdout;
466# ifdef KBUILD_OS_WINDOWS
467 if (maybe_con_fwrite (src, len, 1, f) < 0)
468 ret = -1;
469# else
470 fwrite (src, len, 1, f);
471# endif
472 if (fflush (f) == EOF)
473 ret = -1;
474 }
475 else
476 {
477 /* Work the buffer line by line, replacing each \n with \r\n. */
478 while (len > 0)
479 {
480 const char *nl = memchr ( src, '\n', len);
481 size_t line_len = nl ? nl - src : len;
482 output_write_bin (out, is_err, src, line_len);
483 if (!nl)
484 break;
485 output_write_bin (out, is_err, "\r\n", 2);
486 len -= line_len + 1;
487 src += line_len + 1;
488 }
489 }
490 return ret;
491# else
492 return output_write_bin (out, is_err, src, len);
493# endif
494#else
495 ssize_t ret = len;
496 if (! out || ! out->syncout)
497 {
498 FILE *f = is_err ? stderr : stdout;
499# ifdef KBUILD_OS_WINDOWS
500 maybe_con_fwrite(src, len, 1, f);
501# else
502 fwrite (src, len, 1, f);
503# endif
504 fflush (f);
505 }
506 else
507 {
508 int fd = is_err ? out->err : out->out;
509 int r;
510
511 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
512 while (1)
513 {
514 EINTRLOOP (r, write (fd, src, len));
515 if ((size_t)r == len || r <= 0)
516 break;
517 len -= r;
518 src += r;
519 }
520 }
521 return ret;
522#endif
523}
524
525
526
527/* Write a string to the current STDOUT or STDERR. */
528static void
529_outputs (struct output *out, int is_err, const char *msg)
530{
531#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
532 output_write_text (out, is_err, msg, strlen (msg));
533#else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
534 if (! out || ! out->syncout)
535 {
536 FILE *f = is_err ? stderr : stdout;
537# ifdef KBUILD_OS_WINDOWS
538 maybe_con_fwrite(msg, strlen(msg), 1, f);
539# else
540 fputs (msg, f);
541# endif
542 fflush (f);
543 }
544 else
545 {
546 int fd = is_err ? out->err : out->out;
547 int len = strlen (msg);
548 int r;
549
550 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
551 while (1)
552 {
553 EINTRLOOP (r, write (fd, msg, len));
554 if (r == len || r <= 0)
555 break;
556 len -= r;
557 msg += r;
558 }
559 }
560#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
561}
562
563
564/* Write a message indicating that we've just entered or
565 left (according to ENTERING) the current directory. */
566
567static int
568log_working_directory (int entering)
569{
570 static char *buf = NULL;
571 static unsigned int len = 0;
572 unsigned int need;
573 const char *fmt;
574 char *p;
575
576 /* Get enough space for the longest possible output. */
577 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
578 if (starting_directory)
579 need += strlen (starting_directory);
580
581 /* Use entire sentences to give the translators a fighting chance. */
582 if (makelevel == 0)
583 if (starting_directory == 0)
584 if (entering)
585 fmt = _("%s: Entering an unknown directory\n");
586 else
587 fmt = _("%s: Leaving an unknown directory\n");
588 else
589 if (entering)
590 fmt = _("%s: Entering directory '%s'\n");
591 else
592 fmt = _("%s: Leaving directory '%s'\n");
593 else
594 if (starting_directory == 0)
595 if (entering)
596 fmt = _("%s[%u]: Entering an unknown directory\n");
597 else
598 fmt = _("%s[%u]: Leaving an unknown directory\n");
599 else
600 if (entering)
601 fmt = _("%s[%u]: Entering directory '%s'\n");
602 else
603 fmt = _("%s[%u]: Leaving directory '%s'\n");
604
605 need += strlen (fmt);
606
607 if (need > len)
608 {
609 buf = xrealloc (buf, need);
610 len = need;
611 }
612
613 p = buf;
614 if (print_data_base_flag)
615 {
616 *(p++) = '#';
617 *(p++) = ' ';
618 }
619
620 if (makelevel == 0)
621 if (starting_directory == 0)
622 sprintf (p, fmt , program);
623 else
624 sprintf (p, fmt, program, starting_directory);
625 else if (starting_directory == 0)
626 sprintf (p, fmt, program, makelevel);
627 else
628 sprintf (p, fmt, program, makelevel, starting_directory);
629
630 _outputs (NULL, 0, buf);
631
632 return 1;
633}
634
635/* Set a file descriptor to be in O_APPEND mode.
636 If it fails, just ignore it. */
637
638static void
639set_append_mode (int fd)
640{
641#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
642 int flags = fcntl (fd, F_GETFL, 0);
643 if (flags >= 0)
644 fcntl (fd, F_SETFL, flags | O_APPEND);
645#endif
646}
647
648
649
650#ifndef NO_OUTPUT_SYNC
651
652/* Semaphore for use in -j mode with output_sync. */
653static sync_handle_t sync_handle = -1;
654
655#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
656
657/* Set up the sync handle. Disables output_sync on error. */
658static int
659sync_init (void)
660{
661 int combined_output = 0;
662
663#ifdef WINDOWS32
664# ifdef CONFIG_NEW_WIN_CHILDREN
665 if (STREAM_OK (stdout))
666 {
667 if (STREAM_OK (stderr))
668 {
669 char mtxname[256];
670 sync_handle = create_mutex (mtxname, sizeof (mtxname));
671 if (sync_handle != -1)
672 {
673 prepare_mutex_handle_string (mtxname);
674 return same_stream (stdout, stderr);
675 }
676 perror_with_name ("output-sync suppressed: ", "create_mutex");
677 }
678 else
679 perror_with_name ("output-sync suppressed: ", "stderr");
680 }
681 else
682 perror_with_name ("output-sync suppressed: ", "stdout");
683 output_sync = OUTPUT_SYNC_NONE;
684
685# else /* !CONFIG_NEW_WIN_CHILDREN */
686 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
687 || (sync_handle = create_mutex ()) == -1)
688 {
689 perror_with_name ("output-sync suppressed: ", "stderr");
690 output_sync = 0;
691 }
692 else
693 {
694 combined_output = same_stream (stdout, stderr);
695 prepare_mutex_handle_string (sync_handle);
696 }
697# endif /* !CONFIG_NEW_WIN_CHILDREN */
698
699#else
700 if (STREAM_OK (stdout))
701 {
702 struct stat stbuf_o, stbuf_e;
703
704 sync_handle = fileno (stdout);
705 combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
706 && fstat (fileno (stderr), &stbuf_e) == 0
707 && stbuf_o.st_dev == stbuf_e.st_dev
708 && stbuf_o.st_ino == stbuf_e.st_ino);
709 }
710 else if (STREAM_OK (stderr))
711 sync_handle = fileno (stderr);
712 else
713 {
714 perror_with_name ("output-sync suppressed: ", "stderr");
715 output_sync = 0;
716 }
717#endif
718
719 return combined_output;
720}
721
722#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
723/* Support routine for output_sync() */
724static void
725pump_from_tmp (int from, FILE *to)
726{
727# ifdef KMK
728 char buffer[8192];
729# else
730 static char buffer[8192];
731#endif
732
733# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
734 int prev_mode;
735
736 /* "from" is opened by open_tmpfd, which does it in binary mode, so
737 we need the mode of "to" to match that. */
738 prev_mode = _setmode (fileno (to), O_BINARY);
739#endif
740
741 if (lseek (from, 0, SEEK_SET) == -1)
742 perror ("lseek()");
743
744 while (1)
745 {
746 int len;
747 EINTRLOOP (len, read (from, buffer, sizeof (buffer)));
748 if (len < 0)
749 perror ("read()");
750 if (len <= 0)
751 break;
752 if (fwrite (buffer, len, 1, to) < 1)
753 {
754 perror ("fwrite()");
755 break;
756 }
757 fflush (to);
758 }
759
760# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
761 /* Switch "to" back to its original mode, so that log messages by
762 Make have the same EOL format as without --output-sync. */
763 _setmode (fileno (to), prev_mode);
764#endif
765}
766#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
767
768/* Obtain the lock for writing output. */
769static void *
770acquire_semaphore (void)
771{
772 static struct flock fl;
773
774 fl.l_type = F_WRLCK;
775 fl.l_whence = SEEK_SET;
776 fl.l_start = 0;
777 fl.l_len = 1;
778 if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
779 return &fl;
780#ifdef KBUILD_OS_DARWIN /* F_SETLKW isn't supported on pipes */
781 if (errno != EBADF)
782#endif
783 perror ("fcntl()");
784 return NULL;
785}
786
787/* Release the lock for writing output. */
788static void
789release_semaphore (void *sem)
790{
791 struct flock *flp = (struct flock *)sem;
792 flp->l_type = F_UNLCK;
793 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
794 perror ("fcntl()");
795}
796
797#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
798
799/* Returns a file descriptor to a temporary file. The file is automatically
800 closed/deleted on exit. Don't use a FILE* stream. */
801int
802output_tmpfd (void)
803{
804 int fd = -1;
805 FILE *tfile = tmpfile ();
806
807 if (! tfile)
808 {
809#ifdef KMK
810 if (output_context && output_context->syncout)
811 output_context->syncout = 0; /* Avoid inifinit recursion. */
812#endif
813 pfatal_with_name ("tmpfile");
814 }
815
816 /* Create a duplicate so we can close the stream. */
817 fd = dup (fileno (tfile));
818 if (fd < 0)
819 {
820#ifdef KMK
821 if (output_context && output_context->syncout)
822 output_context->syncout = 0; /* Avoid inifinit recursion. */
823#endif
824 pfatal_with_name ("dup");
825 }
826
827 fclose (tfile);
828
829 set_append_mode (fd);
830
831 return fd;
832}
833
834/* Adds file descriptors to the child structure to support output_sync; one
835 for stdout and one for stderr as long as they are open. If stdout and
836 stderr share a device they can share a temp file too.
837 Will reset output_sync on error. */
838static void
839setup_tmpfile (struct output *out)
840{
841 /* Is make's stdout going to the same place as stderr? */
842 static int combined_output = -1;
843
844 if (combined_output < 0)
845 {
846#ifdef KMK /* prevent infinite recursion if sync_init() calls perror_with_name. */
847 combined_output = 0;
848#endif
849 combined_output = sync_init ();
850 }
851
852 if (STREAM_OK (stdout))
853 {
854 int fd = output_tmpfd ();
855 if (fd < 0)
856 goto error;
857 CLOSE_ON_EXEC (fd);
858 out->out = fd;
859 }
860
861 if (STREAM_OK (stderr))
862 {
863 if (out->out != OUTPUT_NONE && combined_output)
864 out->err = out->out;
865 else
866 {
867 int fd = output_tmpfd ();
868 if (fd < 0)
869 goto error;
870 CLOSE_ON_EXEC (fd);
871 out->err = fd;
872 }
873 }
874
875 return;
876
877 /* If we failed to create a temp file, disable output sync going forward. */
878 error:
879 output_close (out);
880 output_sync = OUTPUT_SYNC_NONE;
881}
882
883#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
884
885/* Synchronize the output of jobs in -j mode to keep the results of
886 each job together. This is done by holding the results in temp files,
887 one for stdout and potentially another for stderr, and only releasing
888 them to "real" stdout/stderr when a semaphore can be obtained. */
889
890void
891output_dump (struct output *out)
892{
893#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
894 membuf_dump (out);
895#else
896 int outfd_not_empty = FD_NOT_EMPTY (out->out);
897 int errfd_not_empty = FD_NOT_EMPTY (out->err);
898
899 if (outfd_not_empty || errfd_not_empty)
900 {
901 int traced = 0;
902
903 /* Try to acquire the semaphore. If it fails, dump the output
904 unsynchronized; still better than silently discarding it.
905 We want to keep this lock for as little time as possible. */
906 void *sem = acquire_semaphore ();
907
908# ifndef KMK /* this drives me bananas. */
909 /* Log the working directory for this dump. */
910 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
911 traced = log_working_directory (1);
912# endif
913
914 if (outfd_not_empty)
915 pump_from_tmp (out->out, stdout);
916 if (errfd_not_empty && out->err != out->out)
917 pump_from_tmp (out->err, stderr);
918
919# ifndef KMK /* this drives me bananas. */
920 if (traced)
921 log_working_directory (0);
922# endif
923
924 /* Exit the critical section. */
925 if (sem)
926 release_semaphore (sem);
927
928 /* Truncate and reset the output, in case we use it again. */
929 if (out->out != OUTPUT_NONE)
930 {
931 int e;
932 lseek (out->out, 0, SEEK_SET);
933 EINTRLOOP (e, ftruncate (out->out, 0));
934 }
935 if (out->err != OUTPUT_NONE && out->err != out->out)
936 {
937 int e;
938 lseek (out->err, 0, SEEK_SET);
939 EINTRLOOP (e, ftruncate (out->err, 0));
940 }
941 }
942#endif
943}
944#endif /* NO_OUTPUT_SYNC */
945
946
947
948/* Provide support for temporary files. */
949
950#ifndef HAVE_STDLIB_H
951# ifdef HAVE_MKSTEMP
952int mkstemp (char *template);
953# else
954char *mktemp (char *template);
955# endif
956#endif
957
958FILE *
959output_tmpfile (char **name, const char *template)
960{
961#ifdef HAVE_FDOPEN
962 int fd;
963#endif
964
965#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
966# define TEMPLATE_LEN strlen (template)
967#else
968# define TEMPLATE_LEN L_tmpnam
969#endif
970 *name = xmalloc (TEMPLATE_LEN + 1);
971 strcpy (*name, template);
972
973#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
974 /* It's safest to use mkstemp(), if we can. */
975 fd = mkstemp (*name);
976 if (fd == -1)
977 return 0;
978 return fdopen (fd, "w");
979#else
980# ifdef HAVE_MKTEMP
981 (void) mktemp (*name);
982# else
983 (void) tmpnam (*name);
984# endif
985
986# ifdef HAVE_FDOPEN
987 /* Can't use mkstemp(), but guard against a race condition. */
988 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
989 if (fd == -1)
990 return 0;
991 return fdopen (fd, "w");
992# else
993 /* Not secure, but what can we do? */
994 return fopen (*name, "w");
995# endif
996#endif
997}
998
999
1000
1001/* This code is stolen from gnulib.
1002 If/when we abandon the requirement to work with K&R compilers, we can
1003 remove this (and perhaps other parts of GNU make!) and migrate to using
1004 gnulib directly.
1005
1006 This is called only through atexit(), which means die() has already been
1007 invoked. So, call exit() here directly. Apparently that works...?
1008*/
1009
1010/* Close standard output, exiting with status 'exit_failure' on failure.
1011 If a program writes *anything* to stdout, that program should close
1012 stdout and make sure that it succeeds before exiting. Otherwise,
1013 suppose that you go to the extreme of checking the return status
1014 of every function that does an explicit write to stdout. The last
1015 printf can succeed in writing to the internal stream buffer, and yet
1016 the fclose(stdout) could still fail (due e.g., to a disk full error)
1017 when it tries to write out that buffered data. Thus, you would be
1018 left with an incomplete output file and the offending program would
1019 exit successfully. Even calling fflush is not always sufficient,
1020 since some file systems (NFS and CODA) buffer written/flushed data
1021 until an actual close call.
1022
1023 Besides, it's wasteful to check the return value from every call
1024 that writes to stdout -- just let the internal stream state record
1025 the failure. That's what the ferror test is checking below.
1026
1027 It's important to detect such failures and exit nonzero because many
1028 tools (most notably 'make' and other build-management systems) depend
1029 on being able to detect failure in other tools via their exit status. */
1030
1031static void
1032close_stdout (void)
1033{
1034 int prev_fail = ferror (stdout);
1035 int fclose_fail = fclose (stdout);
1036
1037 if (prev_fail || fclose_fail)
1038 {
1039 if (fclose_fail)
1040 perror_with_name (_("write error: stdout"), "");
1041 else
1042 O (error, NILF, _("write error: stdout"));
1043 exit (MAKE_TROUBLE);
1044 }
1045}
1046
1047
1048
1049void
1050output_init (struct output *out)
1051{
1052 if (out)
1053 {
1054#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1055 out->out.head_seg = NULL;
1056 out->out.tail_seg = NULL;
1057 out->out.head_run = NULL;
1058 out->out.tail_run = NULL;
1059 out->err.head_seg = NULL;
1060 out->err.tail_seg = NULL;
1061 out->err.head_run = NULL;
1062 out->err.tail_run = NULL;
1063 out->err.total = 0;
1064 out->out.total = 0;
1065 out->seqno = 0;
1066#else
1067 out->out = out->err = OUTPUT_NONE;
1068#endif
1069 out->syncout = !!output_sync;
1070 return;
1071 }
1072
1073 /* Configure this instance of make. Be sure stdout is line-buffered. */
1074
1075#ifdef HAVE_SETVBUF
1076# ifdef SETVBUF_REVERSED
1077 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
1078# else /* setvbuf not reversed. */
1079 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
1080 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
1081# endif /* setvbuf reversed. */
1082#elif HAVE_SETLINEBUF
1083 setlinebuf (stdout);
1084#endif /* setlinebuf missing. */
1085
1086 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
1087 lose output due to overlapping writes. */
1088 set_append_mode (fileno (stdout));
1089 set_append_mode (fileno (stderr));
1090
1091#ifdef HAVE_ATEXIT
1092 if (STREAM_OK (stdout))
1093 atexit (close_stdout);
1094#endif
1095}
1096
1097void
1098output_close (struct output *out)
1099{
1100 if (! out)
1101 {
1102 if (stdio_traced)
1103 log_working_directory (0);
1104 return;
1105 }
1106
1107#ifndef NO_OUTPUT_SYNC
1108 output_dump (out);
1109#endif
1110
1111#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1112 assert (out->out.total == 0);
1113 assert (out->out.head_seg == NULL);
1114 assert (out->err.total == 0);
1115 assert (out->err.head_seg == NULL);
1116#else
1117 if (out->out >= 0)
1118 close (out->out);
1119 if (out->err >= 0 && out->err != out->out)
1120 close (out->err);
1121#endif
1122
1123 output_init (out);
1124}
1125
1126/* We're about to generate output: be sure it's set up. */
1127void
1128output_start (void)
1129{
1130#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1131 /* If we're syncing output make sure the sempahore (win) is set up. */
1132 if (output_context && output_context->syncout)
1133 if (combined_output < 0)
1134 combined_output = sync_init ();
1135#else
1136#ifndef NO_OUTPUT_SYNC
1137 /* If we're syncing output make sure the temporary file is set up. */
1138 if (output_context && output_context->syncout)
1139 if (! OUTPUT_ISSET(output_context))
1140 setup_tmpfile (output_context);
1141#endif
1142#endif
1143
1144#ifndef KMK
1145 /* If we're not syncing this output per-line or per-target, make sure we emit
1146 the "Entering..." message where appropriate. */
1147 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1148#else
1149 /* Indiscriminately output "Entering..." and "Leaving..." message for each
1150 command line or target is plain annoying! And when there is no recursion
1151 it's actually inappropriate. Haven't got a simple way of detecting that,
1152 so back to the old behavior for now. [bird] */
1153#endif
1154 if (! stdio_traced && print_directory_flag)
1155 stdio_traced = log_working_directory (1);
1156}
1157
1158void
1159outputs (int is_err, const char *msg)
1160{
1161 if (! msg || *msg == '\0')
1162 return;
1163
1164 output_start ();
1165
1166 _outputs (output_context, is_err, msg);
1167}
1168
1169
1170
1171static struct fmtstring
1172 {
1173 char *buffer;
1174 size_t size;
1175 } fmtbuf = { NULL, 0 };
1176
1177static char *
1178get_buffer (size_t need)
1179{
1180 /* Make sure we have room. NEED includes space for \0. */
1181 if (need > fmtbuf.size)
1182 {
1183 fmtbuf.size += need * 2;
1184 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1185 }
1186
1187 fmtbuf.buffer[need-1] = '\0';
1188
1189 return fmtbuf.buffer;
1190}
1191
1192/* Print a message on stdout. */
1193
1194void
1195message (int prefix, size_t len, const char *fmt, ...)
1196{
1197 va_list args;
1198 char *p;
1199
1200 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1201 p = get_buffer (len);
1202
1203 if (prefix)
1204 {
1205 if (makelevel == 0)
1206 sprintf (p, "%s: ", program);
1207 else
1208 sprintf (p, "%s[%u]: ", program, makelevel);
1209 p += strlen (p);
1210 }
1211
1212 va_start (args, fmt);
1213 vsprintf (p, fmt, args);
1214 va_end (args);
1215
1216 strcat (p, "\n");
1217
1218 assert (fmtbuf.buffer[len-1] == '\0');
1219 outputs (0, fmtbuf.buffer);
1220}
1221
1222/* Print an error message. */
1223
1224void
1225error (const floc *flocp, size_t len, const char *fmt, ...)
1226{
1227 va_list args;
1228 char *p;
1229
1230 len += (strlen (fmt) + strlen (program)
1231 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1232 + INTSTR_LENGTH + 4 + 1 + 1);
1233 p = get_buffer (len);
1234
1235 if (flocp && flocp->filenm)
1236 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1237 else if (makelevel == 0)
1238 sprintf (p, "%s: ", program);
1239 else
1240 sprintf (p, "%s[%u]: ", program, makelevel);
1241 p += strlen (p);
1242
1243 va_start (args, fmt);
1244 vsprintf (p, fmt, args);
1245 va_end (args);
1246
1247 strcat (p, "\n");
1248
1249 assert (fmtbuf.buffer[len-1] == '\0');
1250 outputs (1, fmtbuf.buffer);
1251}
1252
1253/* Print an error message and exit. */
1254
1255void
1256fatal (const floc *flocp, size_t len, const char *fmt, ...)
1257{
1258 va_list args;
1259 const char *stop = _(". Stop.\n");
1260 char *p;
1261
1262 len += (strlen (fmt) + strlen (program)
1263 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1264 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1265 p = get_buffer (len);
1266
1267 if (flocp && flocp->filenm)
1268 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1269 else if (makelevel == 0)
1270 sprintf (p, "%s: *** ", program);
1271 else
1272 sprintf (p, "%s[%u]: *** ", program, makelevel);
1273 p += strlen (p);
1274
1275 va_start (args, fmt);
1276 vsprintf (p, fmt, args);
1277 va_end (args);
1278
1279 strcat (p, stop);
1280
1281 assert (fmtbuf.buffer[len-1] == '\0');
1282 outputs (1, fmtbuf.buffer);
1283
1284 die (MAKE_FAILURE);
1285}
1286
1287/* Print an error message from errno. */
1288
1289void
1290perror_with_name (const char *str, const char *name)
1291{
1292 const char *err = strerror (errno);
1293 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1294}
1295
1296/* Print an error message from errno and exit. */
1297
1298void
1299pfatal_with_name (const char *name)
1300{
1301 const char *err = strerror (errno);
1302 OSS (fatal, NILF, _("%s: %s"), name, err);
1303
1304 /* NOTREACHED */
1305}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use