<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 - [coroutines] Compiler incorrectly caches thread_local address across suspend-points"
href="https://bugs.llvm.org/show_bug.cgi?id=47835">47835</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[coroutines] Compiler incorrectly caches thread_local address across suspend-points
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</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>C++2a
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>lewissbaker@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>The clang compiler is incorrectly caching the address of thread_local variables
across a suspend-point. It's possible that a coroutine could suspend and later
resume on a different thread, however, which could mean that the thread_local
instance from another thread might be accessed.
Godbolt: <a href="https://godbolt.org/z/o1djvq">https://godbolt.org/z/o1djvq</a>
For example compile the following program with: -std=c++20 -stdlib=libc++ -O2
-pthread
---
#include <experimental/coroutine>
#include <thread>
#include <unistd.h>
#include <pthread.h>
auto switch_to_new_thread(std::thread& out) {
struct awaitable {
std::thread* p_out;
bool await_ready() { return false; }
void await_suspend(std::experimental::coroutine_handle<> h) {
std::thread& out = *p_out;
out = std::thread([h]() mutable {
h.resume();
});
}
void await_resume() {}
};
return awaitable{&out};
}
struct task{
struct promise_type {
task get_return_object() { return {}; }
std::experimental::suspend_never initial_suspend() { return {}; }
std::experimental::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
};
thread_local int tls_variable = 0;
static task resuming_on_new_thread(std::thread& out) {
int* i = &tls_variable;
co_await switch_to_new_thread(out);
int* j = &tls_variable;
std::puts((i == j) ? "tls_variable address was same" : "tls_variable address
was different");
}
int main() {
std::thread out;
resuming_on_new_thread(out);
out.join();
}
------
Expected output: "tls_variable address was different"
Actual output: "tls_variable address was same"
If you compile with -O0 then it correctly outputs "tls_variable address was
different".</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>