<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - std::ifstream makes an unwarranted read, thereby blocking when it shouldn't in a certain case"
   href="https://bugs.llvm.org/show_bug.cgi?id=47087">47087</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>std::ifstream makes an unwarranted read, thereby blocking when it shouldn't in a certain case
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>10.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Standards Issues
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>victor.dods@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=23835" name="attach_23835" title="Source code for "named pipes process" for reproducing bug">attachment 23835</a> <a href="attachment.cgi?id=23835&action=edit" title="Source code for "named pipes process" for reproducing bug">[details]</a></span>
Source code for "named pipes process" for reproducing bug

In working with named pipes (via mkfifo), I've run across a bug in libc++
(relative to what seems to be expected, working behavior in libstdc++)
regarding std::ifstream's buffering behavior.

In particular, two fifos are created, and two processes open them, one for
sending data in each direction.  There is an exchange of data, each process
taking turns reading from the respective fifo.  But certain read operations
block, apparently due to an extra read happening.

Here are the reproduction instructions.  I've also attached source code and a
build script.  I'm using g++-8 and clang++-10 here, but I imagine it doesn't
matter exactly what versions of the compilers are, so long as they're
compatible with libc++ and libstdc++.

Instructions follow:

Compile using each compiler, against each C++ std lib implementation.

build.sh follows (indentation only for clarity):

     #!/bin/bash -ex

     # Compile with clang++-10, link to libc++
     clang++-10 -stdlib=libc++ -g -std=c++17 namedpipes.cpp -o
namedpipes.clang++-10.libc++

     # Compile with clang++-10, link to libstdc++
     clang++-10 -stdlib=libstdc++ -g -std=c++17 namedpipes.cpp -o
namedpipes.clang++-10.libstdc++ -lstdc++fs

     # Compile with g++-8, link to libstdc++
     g++-8 -std=c++17 -g -rdynamic namedpipes.cpp -o namedpipes.g++-8.libstdc++
-lstdc++fs

     # Compile with g++-8, link to libc++
     # Note that it's nontrivial to get g++ to link libc++.
     # See <a href="https://libcxx.llvm.org/docs/UsingLibcxx.html#using-libc-with-gcc">https://libcxx.llvm.org/docs/UsingLibcxx.html#using-libc-with-gcc</a>
     LIBCPP_INCLUDE_DIR=/usr/lib/llvm-10/include/c++/v1
     g++-8 -std=c++17 -nostdinc++ -I${LIBCPP_INCLUDE_DIR} -g -rdynamic
namedpipes.cpp -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc -o
namedpipes.g++-8.libc++

Note that the bug here is happening against libc++.


Run as a pair of processes, one in each terminal.

     ./namedpipes.g++-8.libstdc++ p0
     ./namedpipes.g++-8.libstdc++ p1

The g++-8 libstdc++ one works as expected.


Run as a pair of processes, one in each terminal, each one run under strace.

     strace ./namedpipes.clang++-10.libc++ p0
     strace ./namedpipes.clang++-10.libc++ p1

You'll see that p0 blocks with

     write(2, "p0: about to read ... ", 22p0: about to read ... )  = 22
     fstat(4, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
     read(4,

and p1 blocks with

     write(2, "p1: about to read ... ", 22p1: about to read ... )  = 22
     fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
     read(3, "a", 4096)                      = 1
     read(3,

where the last read() is the unwarranted, blocking one that's causing the
problems.


If you run the g++ binaries under strace, you'll see that p1 does not block:

     write(2, "p1: about to read ... ", 22p1: about to read ... )  = 22
     read(3, "a", 1)                         = 1
     write(2, "success; read '", 15success; read ')         = 15

Notice that there was only one call to read(), so it didn't block.


The same holds when you switch the compiler but keep the C++ std lib choice the
same,
i.e. libstdc++ works as expected, and libc++ blocks.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>