<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 - LLD's termination code does not allow code coverage analysis to work properly."
   href="https://bugs.llvm.org/show_bug.cgi?id=38104">38104</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>LLD's termination code does not allow code coverage analysis to work properly.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>lld
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

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

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

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

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>ELF
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>grimar@accesssoftek.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=20542" name="attach_20542" title="callstack">attachment 20542</a> <a href="attachment.cgi?id=20542&action=edit" title="callstack">[details]</a></span>
callstack

I am not sure we can call it a bug of LLD, though it seems at least something
worth to document. (And maybe to improve somehow).

Currently, LLD uses _exit for error() and fatal() calls:
<a href="https://github.com/llvm-mirror/lld/blob/master/Common/ErrorHandler.cpp#L60">https://github.com/llvm-mirror/lld/blob/master/Common/ErrorHandler.cpp#L60</a>

That does not allow to test code coverage properly sometimes.

Imagine the following code:

#include <stdlib.h>
#include <unistd.h>

__attribute__((noreturn)) void fatal() {
  exit(0);
}

int main() {
  fatal();
  return 0;
}

If we compile and run it as
clang++ test.c --coverage -fPIC -std=c++11 -fprofile-arcs -ftest-coverage -o
test
./test
We'll see the .gcno and .gcda created and will be able to generate the coverage
report:
~/LLVM/build/bin/llvm-cov gcov test.gcda

But if we change "exit" to "_exit", then no .gcda file is created after running
the app.
That happens because _exit does not do enough cleaning, buffers flushing etc.

The same happens with LLD. If I change "_exit" to "exit" at a mentioned line,
it allows obtaining the correct reports about code coverage.

There is a problem about race conditions though. When using exit() LLD hangs
during
running the tests when multithreading is enabled. I was able to catch
and debug it (reproduces on invalid-cie-length.s test case for me).
Screenshot attached shows how 2 threads are stuck in destructors and waiting
for something.

The issue happens in the following code:
<a href="https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Parallel.cpp#L94">https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Parallel.cpp#L94</a>
At line 103 we call the Task() functor. Here Task() calls fatal() inside, which
is "noreturn" and
calls _exit originally. After changing _exit() to exit(), the code starts to
execute static destructors
and we stuck because of that in the ~ThreadPoolExecutor which waits for ~Latch
infinitely
because line 105 ("Done.dec();") is never executed.

The case above happens because we call fatal() in the parrallel_foreach thread.
That particular fatal() is coming from EhFrame parser:
<a href="https://github.com/llvm-mirror/lld/blob/master/ELF/EhFrame.cpp#L46">https://github.com/llvm-mirror/lld/blob/master/ELF/EhFrame.cpp#L46</a>
It should be possible to workaround that race condition if we will use error()
instead of fatal(), which usually does not exit immediately.
It might be enough for building coverage report purposes.</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>