bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gawk vs stdout: an alternative proposal (gawk doesn't report disk full!)


From: Jim Meyering
Subject: gawk vs stdout: an alternative proposal (gawk doesn't report disk full!)
Date: Thu, 30 Jun 2005 14:52:07 +0200

Hi Arnold,

Here's a way to solve one of gawk's closed-stdout problem:

When standard output (or stderr) is initially closed, make gawk
open /dev/null *read-only* to get the new file descriptor.
(currently it opens for read/write access)
Similarly, when standard input is initially closed,
open /dev/null *write-only*.

Here's a little motivation:
Without the change below, gawk doesn't diagnose some write failures.
Each of these commands gets a failed write, yet
both exit successfully and give no diagnostic:

  gawk --help >&-
  gawk 'BEGIN {print x}' >&-

As you recall, an awk script that writes to closed stdout
cannot portably expect either behavior, since some other
implementations already fail in that case.

With the patch below, we get part of what we want.
Now, the first exits nonzero (but no diagnostic), and the second
gives a diagnostic (but still exits successfully):

  $ ./gawk --help >&- || echo Fail
  Fail
  $ ./gawk 'BEGIN {print x}' >&-
  gawk: warning: error writing standard output (Bad file descriptor)

2005-06-30  Jim Meyering  <address@hidden>

        * main.c (init_fds): If any of the STDIN_FILENO, STDOUT_FILENO,
        STDERR_FILENO are initially closed, reopen them with permissions
        contrary to common usage so that any reasonable attempt to use
        them will evoke the same sort of error as reading or writing to
        a closed file descriptor would.

--- main.c.~1~  2005-05-11 17:28:16.000000000 +0200
+++ main.c      2005-06-30 12:40:27.677089722 +0200
@@ -1109,6 +1109,7 @@ init_fds()
        struct stat sbuf;
        int fd;
        int newfd;
+       char const *const opposite_mode[] = {"w", "r", "r"};
 
        /* maybe no stderr, don't bother with error mesg */
        for (fd = 0; fd <= 2; fd++) {
@@ -1117,7 +1118,7 @@ init_fds()
                        if (do_lint)
                                lintwarn(_("no pre-opened fd %d"), fd);
 #endif
-                       newfd = devopen("/dev/null", "r+");
+                       newfd = devopen("/dev/null", opposite_mode[fd]);
                        /* turn off some compiler warnings "set but not used" */
                        newfd += 0;
 #ifdef MAKE_A_HEROIC_EFFORT

As for why a failed write evokes a diagnostic, but gawk itself
exits successfully, I see this comment in main.c:

        /*
         * This used to be:
         *
         * if (close_io() != 0 && ! exiting && exit_val == 0)
         *      exit_val = 1;
         *
         * Other awks don't care about problems closing open files
         * and pipes, in that it doesn't affect their exit status.
         * So we no longer do either.
         */
        (void) close_io();

Perhaps that is the right thing to do with user-opened files and pipes,
but when gawk itself fails to close stdout, it *must* exit nonzero.
It should probably do the same if closing stderr fails, too.

Currently, either with or without the above patch, gawk mistakenly exits
successfully when writing to a full device or upon I/O error, e.g.,

  ./gawk 'BEGIN {print x}' > /dev/full; echo $?
  gawk: warning: error writing standard output (No space left on device)
  0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]