<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 - possible deadlock in termination path on Windows"
href="https://bugs.llvm.org/show_bug.cgi?id=43389">43389</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>possible deadlock in termination path on Windows
</td>
</tr>
<tr>
<th>Product</th>
<td>libc++
</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>All Bugs
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>compnerd@compnerd.org
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
</td>
</tr></table>
<p>
<div>
<pre>Consider the following program:
```
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <thread>
int main()
{
std::setvbuf(stdout, NULL, _IOLBF, 0x1000);
std::cout << "Hello, world!";
_lock_file(stdout);
std::thread t([&] { std::_Exit(0); });
t.join();
return 0;
}
```
The `std::_Exit` will invoke the DLL destructors, from the invoking thread and
after terminating all other threads in the process. Because the main thread
was holding the lock on `stdout` when it was terminated, this will result in an
orphaned CriticalSection which the DLL destructor will attempt to acquire.
Fortunately, Windows will identify that the CriticalSection is orphaned and
terminate the program. This is not however guaranteed, and if the underlying
libc does not use a CriticalSection to handle the locking, the application may
deadlock.
This is visible to the user by having the program be terminated by a ^C sent to
the application while the application is writing to the console (and thus
acquiring the lock to the output stream). The destructor will attempt to flush
the stream before program termination, which will attempt to re-acquire the now
orphaned lock.
<a href="https://github.com/llvm-mirror/libcxx/blob/master/src/iostream.cpp#L135-L148">https://github.com/llvm-mirror/libcxx/blob/master/src/iostream.cpp#L135-L148</a></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>