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

David Majnemer david.majnemer at gmail.com
Mon Oct 6 17:02:06 PDT 2014


On Mon, Oct 6, 2014 at 4:54 PM, David Blaikie <dblaikie at gmail.com> wrote:

>
>
> On Mon, Oct 6, 2014 at 4:51 PM, David Majnemer <david.majnemer at gmail.com>
> wrote:
>
>> On Mon, Oct 6, 2014 at 4:40 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>
>>>
>>>
>>> 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.
>>>>
>>>
>>> Shouldn't we just fix these places so they don't make that mistake?
>>> (perhaps they should be checking if the FD isatty, etc - or whatever
>>> feature it is they care about)
>>>
>>
>> Your stdout might be a file by the users choice.  It's not possible to
>> determine if stdout is sane by the time we get as far as constructing
>> outs() or errs().
>>
>
> For what definition of sanity?
>

Normal file redirection at the command line can result in standard out
being a normal file:
./foo > bar


>
> Anyway, just curious at what problems this addresses & vaguely wondering
> whether there's a differently general solution as this seems a bit weirdly
> special case to my vague understanding.
>
>
>>
>>>
>>>>
>>>> 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/6993eaae/attachment.html>


More information about the llvm-commits mailing list