[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:51:47 PDT 2014


Man, closing fds 1 and 2 is risky. I wouldn't ever trust all my libraries
not to print to stdout/stderr.

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

> fileno(stdout) will be 1 even if file descriptor 1 is closed.
>
>
> On Mon, Oct 6, 2014 at 4:43 PM, Reid Kleckner <rnk at google.com> wrote:
>
>> 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/85e446ec/attachment.html>


More information about the llvm-commits mailing list