[llvm-bugs] [Bug 47833] New: [coroutines] Clang incorrectly caches result of pthread_self() across coroutine suspend-points
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Oct 13 13:08:20 PDT 2020
https://bugs.llvm.org/show_bug.cgi?id=47833
Bug ID: 47833
Summary: [coroutines] Clang incorrectly caches result of
pthread_self() across coroutine suspend-points
Product: clang
Version: trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: enhancement
Priority: P
Component: C++2a
Assignee: unassignedclangbugs at nondot.org
Reporter: lewissbaker at gmail.com
CC: blitzrakete at gmail.com, erik.pilkington at gmail.com,
llvm-bugs at lists.llvm.org, richard-llvm at metafoo.co.uk
Godbolt: https://godbolt.org/z/zYfvaM
Compile the following program with: -std=c++20 -fcoroutines-ts -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() {}
};
};
static task resuming_on_new_thread(std::thread& out) {
auto id1 = std::this_thread::get_id();
auto pthread1 = pthread_self();
auto pid1 = gettid();
co_await switch_to_new_thread(out);
auto id2 = std::this_thread::get_id();
auto pthread2 = pthread_self();
auto pid2 = gettid();
std::puts((id1 == id2) ? "this_thread::get_id() was same" :
"this_thread::get_id() was different");
std::puts((pid1 == pid2) ? "gettid() was same" : "gettid() was different");
std::puts((pthread1 == pthread2) ? "pthread_self() was same" :
"pthread_self() was different");
}
int main() {
std::thread out;
resuming_on_new_thread(out);
out.join();
}
----
Expected output:
---
this_thread::get_id() was different
gettid() was different
pthread_self() was different
Actual output:
---
this_thread::get_id() was same
gettid() was different
pthread_self() was same
The compiler generates code that calls the pthread_self() function once at the
start of the coroutine and then caches the result in the coroutine frame and
reloads the cached value after the coroutine resumes on another thread, leading
to the second call to pthread_self() seemingly returning the wrong value.
This also affects std::this_thread::get_id(), which is a thin-wrapper over
pthread_self(), and so if get_id() is inlined into the coroutine then it hits
the same problem. If get_id() is not inlined into the coroutine (eg. when using
-O1) then the second std::this_thread::get_id() gives the correct result.
--
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/20201013/d067aa2d/attachment.html>
More information about the llvm-bugs
mailing list