[llvm-bugs] [Bug 49463] New: clang version 11.1.0 - SIGABRT from llvm::raw_fd_ostream::~raw_fd_ostream when stderr redirects to stdin

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Mar 6 12:29:43 PST 2021


https://bugs.llvm.org/show_bug.cgi?id=49463

            Bug ID: 49463
           Summary: clang version 11.1.0 - SIGABRT from
                    llvm::raw_fd_ostream::~raw_fd_ostream when stderr
                    redirects to stdin
           Product: clang
           Version: 11.0
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Frontend
          Assignee: unassignedclangbugs at nondot.org
          Reporter: bertrand at jacquin.bzh
                CC: llvm-bugs at lists.llvm.org, neeilans at live.com,
                    richard-llvm at metafoo.co.uk

Hi,

The following command can be used to verify if a given option is supported by
$CC:

  $CC -Werror -<option> -E -xc - -o /dev/null

(While -Werror is not required for all compiler, clang will always return 0
even if an option is not supported unless -Werror is also passed as an
argument, hence I will keep mentioning -Werror here).

When the option is recognized or supported a return code of 0 is expected, if
the option is not recognized or supported a return code of 1 is expected with
potential warning on stderr. This is useful in the context of Makefile or build
systems to probe which option can be used, for example, to remove a set of
warnings. Those usually redirect all I/O to /dev/null to prevent from polluting
input or output, and instead only rely on return code:

  $CC -Werror -<option> -E -xc - -o /dev/null < /dev/null 1>&0 2>&0

Here is a example using gcc to assess if -Wmissing-field-initializers
(supported by gcc and clang), -Wclobbered (supported by gcc but not by clang)
and -Wfoobar (supported by neither gcc or clang) are supported (tested with gcc
from 6.5 to 10.2):

  $ gcc -Werror -Wmissing-field-initializers -E -xc - -o /dev/null < /dev/null
1>&0 2>&0
  $ echo $?
  0
  $ gcc -Werror -Wclobbered -E -xc - -o /dev/null < /dev/null 1>&0 2>&0
  $ echo $?
  0
  $ gcc -Werror -Wfoobar -E -xc - -o /dev/null < /dev/null 1>&0 2>&0
  $ echo $?
  1

Here is the same example with clang 11.1.0:

  $ clang -Werror -Wmissing-field-initializers -E -xc - -o /dev/null <
/dev/null 1>&0 2>&0
  $ echo $?
  0
  $ clang -Werror -Wclobbered -E -xc - -o /dev/null < /dev/null 1>&0 2>&0
  Aborted (core dumped)
  $ echo $?
  134
  $ clang -Werror -Wfoobar -E -xc - -o /dev/null < /dev/null 1>&0 2>&0
  Aborted (core dumped)
  $ echo $?
  134

The example show that clang triggers a SIGABRT if an option is not supported,
hence generating a warning and if stderr is redirected to stdin. Digging more
into this, I can see stdout does not matter in this case and only the
redirection of stderr to stdin (both /dev/null) triggers the SIGABRT.

Please note if explicit redirection of stderr to the same output as stdin does
not trigger SIGABRT:

  $ clang -Werror -Wfoobar -E -xc - -o /dev/null < /dev/null 2> /dev/null
  $ echo $?
  1

Same applies with no redirection as all:

  $ clang -Werror -Wfoobar -E -xc - -o /dev/null
  error: unknown warning option '-Wfoobar'; did you mean '-Wformat'?
[-Werror,-Wunknown-warning-option]
  $ echo $?
  1

This specific behaviour can be observed with a more simple use case like:

  $ clang --does-not-exist < /dev/null 2>&0
  Aborted (core dumped)
  $ echo $?
  134

Here is a backtrack from gdb with `clang -Werror -Wclobbered -E -xc - -o
/dev/null < /dev/null 1>&0 2>&0`:

  (gdb) bt
  #0  __GI_raise (sig=sig at entry=6) at
/usr/src/debug/sys-libs/glibc-2.32-r8/glibc-2.32/sysdeps/unix/sysv/linux/raise.c:49
  #1  0x00007f7a155205e8 in __GI_abort () at
/usr/src/debug/sys-libs/glibc-2.32-r8/glibc-2.32/stdlib/abort.c:100
  #2  0x00007f7a1624960c in llvm::report_fatal_error (Reason=...,
GenCrashDiag=false)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/ErrorHandling.cpp:126
  #3  0x00007f7a1624940a in llvm::report_fatal_error (Reason=...,
GenCrashDiag=false)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/ErrorHandling.cpp:87
  #4  0x00007f7a1639a3fc in llvm::raw_fd_ostream::~raw_fd_ostream
(this=0x7f7a1c659ca0 <llvm::errs()::S>, __in_chrg=<optimized out>)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/raw_ostream.cpp:685
  #5  0x00007f7a15539a13 in __run_exit_handlers (status=1, listp=0x7f7a156b6598
<__exit_funcs>, run_list_atexit=run_list_atexit at entry=true,
      run_dtors=run_dtors at entry=true) at
/usr/src/debug/sys-libs/glibc-2.32-r8/glibc-2.32/stdlib/exit.c:108
  #6  0x00007f7a15539bbc in __GI_exit (status=<optimized out>) at
/usr/src/debug/sys-libs/glibc-2.32-r8/glibc-2.32/stdlib/exit.c:139
  #7  0x00007f7a15521e41 in __libc_start_main (main=0x55cb2487e3b3 <main(int,
char const**)>, argc=8, argv=0x7fff39b270e8, init=<optimized out>,
      fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fff39b270d8) at
/usr/src/debug/sys-libs/glibc-2.32-r8/glibc-2.32/csu/libc-start.c:348
  #8  0x000055cb2487a95a in _start ()

  (gdb) fr 2
  #2  0x00007f7a1624960c in llvm::report_fatal_error (Reason=...,
GenCrashDiag=false)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/ErrorHandling.cpp:126
  126     abort();
  (gdb) info args
  Reason = @0x7fff39b26ee0: {
    LHS = {
      twine = 0x7fff39b26f40,
      cString = 0x7fff39b26f40 " \315\340$\313U",
      stdString = 0x7fff39b26f40,
      stringRef = 0x7fff39b26f40,
      smallString = 0x7fff39b26f40,
      formatvObject = 0x7fff39b26f40,
      character = 64 '@',
      decUI = 967995200,
      decI = 967995200,
      decUL = 0x7fff39b26f40,
      decL = 0x7fff39b26f40,
      decULL = 0x7fff39b26f40,
      decLL = 0x7fff39b26f40,
      uHex = 0x7fff39b26f40
    },
    RHS = {
      twine = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      cString = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>
"H\213E\370\311\303\220UH\211\345SH\203\354(H\211}\350H\211u\340H\211U\330H\211M\320H\213]\350H\213E\350H\211\307\350w'\366\377H\211\301H\213E\320H\211\302H\211\316H\211\337\350\"\367\364\377H\213U\330H\213M\340H\213E\350H\211\316H\211\307\350\207\004",
      stdString = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      stringRef = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      smallString = 0x7f7a161e8809 <std::operator+<char,
std::char_traits<char>, std::allocator<char> >(char const*,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>&&)+67>,
      formatvObject = 0x7f7a161e8809 <std::operator+<char,
std::char_traits<char>, std::allocator<char> >(char const*,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>&&)+67>,
      character = 9 '\t',
      decUI = 371099657,
      decI = 371099657,
      decUL = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      decL = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      decULL = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      decLL = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>,
      uHex = 0x7f7a161e8809 <std::operator+<char, std::char_traits<char>,
std::allocator<char> >(char const*, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&&)+67>
    },
    LHSKind = llvm::Twine::StdStringKind,
    RHSKind = llvm::Twine::EmptyKind
  }
  GenCrashDiag = false

  (gdb) fr 3
  #3  0x00007f7a1624940a in llvm::report_fatal_error (Reason=...,
GenCrashDiag=false)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/ErrorHandling.cpp:87
  87      report_fatal_error(Twine(Reason), GenCrashDiag);
  (gdb) info args
  Reason = @0x7fff39b26f40: {
    static npos = 18446744073709551615,
    _M_dataplus = {
      <std::allocator<char>> = {
        <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data
fields>},
      members of std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Alloc_hider:
      _M_p = 0x55cb24e0cd20 "IO failure on output stream: Bad file descriptor"
    },
    _M_string_length = 48,
    {
      _M_local_buf = "0\000\000\000\000\000\000\000\062\236S\025z\177\000",
      _M_allocated_capacity = 48
    }
  }
  GenCrashDiag = false

  (gdb) fr 4
  #4  0x00007f7a1639a3fc in llvm::raw_fd_ostream::~raw_fd_ostream
(this=0x7f7a1c659ca0 <llvm::errs()::S>, __in_chrg=<optimized out>)
      at
/usr/src/debug/sys-devel/llvm-11.1.0/llvm/lib/Support/raw_ostream.cpp:685
  685       report_fatal_error("IO failure on output stream: " +
error().message(),
  (gdb) info args
  this = 0x7f7a1c659ca0 <llvm::errs()::S>
  __in_chrg = <optimized out>
  (gdb) print FD
  $2 = 2


The "Bad file descriptor" issue seems to exist since clang 6.0 while only clang
11 (11.0.1 and 11.1.0) do trigger a SIGABRT.

Do you want me to provide a coredump ?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210306/3f20aa07/attachment.html>


More information about the llvm-bugs mailing list