root/maint/gnulib/lib/closeout.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. close_stdout_set_file_name
  2. close_stdout_set_ignore_EPIPE
  3. close_stdout

   1 /* Close standard output and standard error, exiting with a diagnostic on error.
   2 
   3    Copyright (C) 1998-2002, 2004, 2006, 2008-2021 Free Software Foundation,
   4    Inc.
   5 
   6    This program is free software: you can redistribute it and/or modify
   7    it under the terms of the GNU General Public License as published by
   8    the Free Software Foundation; either version 3 of the License, or
   9    (at your option) any later version.
  10 
  11    This program is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU General Public License for more details.
  15 
  16    You should have received a copy of the GNU General Public License
  17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  18 
  19 #include <config.h>
  20 
  21 #include "closeout.h"
  22 
  23 #include <errno.h>
  24 #include <stdbool.h>
  25 #include <stdio.h>
  26 #include <unistd.h>
  27 
  28 #include "gettext.h"
  29 #define _(msgid) gettext (msgid)
  30 
  31 #include "close-stream.h"
  32 #include "error.h"
  33 #include "exitfail.h"
  34 #include "quotearg.h"
  35 
  36 #ifndef __has_feature
  37 # define __has_feature(a) false
  38 #endif
  39 
  40 #if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
  41 enum { SANITIZE_ADDRESS = true };
  42 #else
  43 enum { SANITIZE_ADDRESS = false };
  44 #endif
  45 
  46 static const char *file_name;
  47 
  48 /* Set the file name to be reported in the event an error is detected
  49    by close_stdout.  */
  50 void
  51 close_stdout_set_file_name (const char *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53   file_name = file;
  54 }
  55 
  56 static bool ignore_EPIPE /* = false */;
  57 
  58 /* Specify the reaction to an EPIPE error during the closing of stdout:
  59      - If ignore = true, it shall be ignored.
  60      - If ignore = false, it shall evoke a diagnostic, along with a nonzero
  61        exit status.
  62    The default is ignore = false.
  63 
  64    This setting matters only if the SIGPIPE signal is ignored (i.e. its
  65    handler set to SIG_IGN) or blocked.  Only particular programs need to
  66    temporarily ignore SIGPIPE.  If SIGPIPE is ignored or blocked because
  67    it was ignored or blocked in the parent process when it created the
  68    child process, it usually is a bug in the parent process: It is bad
  69    practice to have SIGPIPE ignored or blocked while creating a child
  70    process.
  71 
  72    EPIPE occurs when writing to a pipe or socket that has no readers now,
  73    when SIGPIPE is ignored or blocked.
  74 
  75    The ignore = false setting is suitable for a scenario where it is normally
  76    guaranteed that the pipe writer terminates before the pipe reader.  In
  77    this case, an EPIPE is an indication of a premature termination of the
  78    pipe reader and should lead to a diagnostic and a nonzero exit status.
  79 
  80    The ignore = true setting is suitable for a scenario where you don't know
  81    ahead of time whether the pipe writer or the pipe reader will terminate
  82    first.  In this case, an EPIPE is an indication that the pipe writer can
  83    stop doing useless write() calls; this is what close_stdout does anyway.
  84    EPIPE is part of the normal pipe/socket shutdown protocol in this case,
  85    and should not lead to a diagnostic message.  */
  86 
  87 void
  88 close_stdout_set_ignore_EPIPE (bool ignore)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   ignore_EPIPE = ignore;
  91 }
  92 
  93 /* Close standard output.  On error, issue a diagnostic and _exit
  94    with status 'exit_failure'.
  95 
  96    Also close standard error.  On error, _exit with status 'exit_failure'.
  97 
  98    Since close_stdout is commonly registered via 'atexit', POSIX
  99    and the C standard both say that it should not call 'exit',
 100    because the behavior is undefined if 'exit' is called more than
 101    once.  So it calls '_exit' instead of 'exit'.  If close_stdout
 102    is registered via atexit before other functions are registered,
 103    the other functions can act before this _exit is invoked.
 104 
 105    Applications that use close_stdout should flush any streams
 106    other than stdout and stderr before exiting, since the call to
 107    _exit will bypass other buffer flushing.  Applications should
 108    be flushing and closing other streams anyway, to check for I/O
 109    errors.  Also, applications should not use tmpfile, since _exit
 110    can bypass the removal of these files.
 111 
 112    It's important to detect such failures and exit nonzero because many
 113    tools (most notably 'make' and other build-management systems) depend
 114    on being able to detect failure in other tools via their exit status.  */
 115 
 116 void
 117 close_stdout (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119   if (close_stream (stdout) != 0
 120       && !(ignore_EPIPE && errno == EPIPE))
 121     {
 122       char const *write_error = _("write error");
 123       if (file_name)
 124         error (0, errno, "%s: %s", quotearg_colon (file_name),
 125                write_error);
 126       else
 127         error (0, errno, "%s", write_error);
 128 
 129       _exit (exit_failure);
 130     }
 131 
 132   /* Close stderr only if not sanitizing, as sanitizers may report to
 133      stderr after this function returns.  */
 134   if (!SANITIZE_ADDRESS && close_stream (stderr) != 0)
 135     _exit (exit_failure);
 136 }

/* [previous][next][first][last][top][bottom][index][help] */