[llvm] r219170 - Support: Add a utility to remap std{in, out, err} to /dev/null if closed

Reid Kleckner rnk at google.com
Mon Oct 6 16:43:43 PDT 2014


I thought we agreed to reduce our reliance on STDOUT_FILENO and instead
check fileno(stdout)?

On Mon, Oct 6, 2014 at 4:16 PM, David Majnemer <david.majnemer at gmail.com>
wrote:

> Author: majnemer
> Date: Mon Oct  6 18:16:18 2014
> New Revision: 219170
>
> URL: http://llvm.org/viewvc/llvm-project?rev=219170&view=rev
> Log:
> Support: Add a utility to remap std{in,out,err} to /dev/null if closed
>
> It's possible to start a program with one (or all) of the standard file
> descriptors closed.  Subsequent open system calls will give the program
> a low-numbered file descriptor.
>
> This is problematic because we may believe we are writing to standard
> out instead of a file.
>
> Introduce Process::FixupStandardFileDescriptors, a helper function to
> remap standard file descriptors to /dev/null if they were closed before
> the program started.
>
> Modified:
>     llvm/trunk/include/llvm/Support/Process.h
>     llvm/trunk/lib/Support/Unix/Process.inc
>     llvm/trunk/lib/Support/Windows/Process.inc
>
> Modified: llvm/trunk/include/llvm/Support/Process.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Process.h?rev=219170&r1=219169&r2=219170&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/Process.h (original)
> +++ llvm/trunk/include/llvm/Support/Process.h Mon Oct  6 18:16:18 2014
> @@ -186,6 +186,12 @@ public:
>                      ArrayRef<const char *> ArgsFromMain,
>                      SpecificBumpPtrAllocator<char> &ArgAllocator);
>
> +  // This functions ensures that the standard file descriptors (input,
> output,
> +  // and error) are properly mapped to a file descriptor before we use
> any of
> +  // them.  This should only be called by standalone programs, library
> +  // components should not call this.
> +  static std::error_code FixupStandardFileDescriptors();
> +
>    /// This function determines if the standard input is connected directly
>    /// to a user's input (keyboard probably), rather than coming from a
> file
>    /// or pipe.
>
> Modified: llvm/trunk/lib/Support/Unix/Process.inc
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Process.inc?rev=219170&r1=219169&r2=219170&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/Unix/Process.inc (original)
> +++ llvm/trunk/lib/Support/Unix/Process.inc Mon Oct  6 18:16:18 2014
> @@ -18,6 +18,9 @@
>  #include "llvm/Support/Mutex.h"
>  #include "llvm/Support/MutexGuard.h"
>  #include "llvm/Support/TimeValue.h"
> +#if HAVE_FCNTL_H
> +#include <fcntl.h>
> +#endif
>  #ifdef HAVE_SYS_TIME_H
>  #include <sys/time.h>
>  #endif
> @@ -199,6 +202,62 @@ Process::GetArgumentVector(SmallVectorIm
>    return std::error_code();
>  }
>
> +namespace {
> +class FDCloser {
> +public:
> +  FDCloser(int &FD) : FD(FD), KeepOpen(false) {}
> +  void keepOpen() { KeepOpen = true; }
> +  ~FDCloser() {
> +    if (!KeepOpen && FD >= 0)
> +      ::close(FD);
> +  }
> +
> +private:
> +  FDCloser(const FDCloser &) LLVM_DELETED_FUNCTION;
> +  void operator=(const FDCloser &) LLVM_DELETED_FUNCTION;
> +
> +  int &FD;
> +  bool KeepOpen;
> +};
> +}
> +
> +std::error_code Process::FixupStandardFileDescriptors() {
> +  int NullFD = -1;
> +  FDCloser FDC(NullFD);
> +  const int StandardFDs[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
> +  for (int StandardFD : StandardFDs) {
> +    struct stat st;
> +    errno = 0;
> +    while (fstat(StandardFD, &st) < 0) {
> +      assert(errno && "expected errno to be set if fstat failed!");
> +      // fstat should return EBADF if the file descriptor is closed.
> +      if (errno == EBADF)
> +        break;
> +      // retry fstat if we got EINTR, otherwise bubble up the failure.
> +      if (errno != EINTR)
> +        return std::error_code(errno, std::generic_category());
> +    }
> +    // if fstat succeeds, move on to the next FD.
> +    if (!errno)
> +      continue;
> +    assert(errno == EBADF && "expected errno to have EBADF at this
> point!");
> +
> +    if (NullFD < 0) {
> +      while ((NullFD = open("/dev/null", O_RDWR)) < 0) {
> +        if (errno == EINTR)
> +          continue;
> +        return std::error_code(errno, std::generic_category());
> +      }
> +    }
> +
> +    if (NullFD == StandardFD)
> +      FDC.keepOpen();
> +    else if (dup2(NullFD, StandardFD) < 0)
> +      return std::error_code(errno, std::generic_category());
> +  }
> +  return std::error_code();
> +}
> +
>  bool Process::StandardInIsUserInput() {
>    return FileDescriptorIsDisplayed(STDIN_FILENO);
>  }
>
> Modified: llvm/trunk/lib/Support/Windows/Process.inc
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=219170&r1=219169&r2=219170&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/Windows/Process.inc (original)
> +++ llvm/trunk/lib/Support/Windows/Process.inc Mon Oct  6 18:16:18 2014
> @@ -273,6 +273,10 @@ Process::GetArgumentVector(SmallVectorIm
>    return ec;
>  }
>
> +std::error_code Process::FixupStandardFileDescriptors() {
> +  return std::error_code();
> +}
> +
>  bool Process::StandardInIsUserInput() {
>    return FileDescriptorIsDisplayed(0);
>  }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141006/8ede3311/attachment.html>


More information about the llvm-commits mailing list