-
Notifications
You must be signed in to change notification settings - Fork 25
Use thread local storage for cancellation none #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,7 +9,6 @@ | |||||||||||||||
| #include <vector> | ||||||||||||||||
|
|
||||||||||||||||
| #include <functional> | ||||||||||||||||
| #include <vector> | ||||||||||||||||
|
|
||||||||||||||||
| namespace arcana | ||||||||||||||||
| { | ||||||||||||||||
|
|
@@ -129,34 +128,9 @@ namespace arcana | |||||||||||||||
| std::atomic<bool> m_cancellationRequested{ false }; | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| namespace internal::no_destroy_cancellation | ||||||||||||||||
| { | ||||||||||||||||
| // To address a problem with static globals recognized as the same as in a | ||||||||||||||||
| // standards proposal, we adopt a workaround described in the proposal. | ||||||||||||||||
| // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1247r0.html | ||||||||||||||||
| template <class T> | ||||||||||||||||
| class no_destroy | ||||||||||||||||
| { | ||||||||||||||||
| alignas(T) unsigned char data_[sizeof(T)]; | ||||||||||||||||
|
|
||||||||||||||||
| public: | ||||||||||||||||
| template <class... Ts> | ||||||||||||||||
| no_destroy(Ts&&... ts) | ||||||||||||||||
| { | ||||||||||||||||
| new (data_)T(std::forward<Ts>(ts)...); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| T &get() | ||||||||||||||||
| { | ||||||||||||||||
| return *reinterpret_cast<T *>(data_); | ||||||||||||||||
| } | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| inline no_destroy<cancellation_source> none{}; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| inline cancellation& cancellation::none() | ||||||||||||||||
| { | ||||||||||||||||
| return internal::no_destroy_cancellation::none.get(); | ||||||||||||||||
| static thread_local cancellation_source n{}; | ||||||||||||||||
|
||||||||||||||||
| static thread_local cancellation_source n{}; | |
| static cancellation_source n{}; |
Copilot
AI
Feb 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cancellation::none() now returns a thread_local cancellation_source. This is unsafe with the current task/cancellation API because tasks capture the cancellation token by reference (see input_output_wrapper::wrap_callable capturing &cancel), so a task created with cancellation::none() can outlive the creating thread and then dereference a destroyed thread-local object (use-after-free). It also breaks the this == &none() fast-path in add_listener() across threads (different thread-local addresses), which can cause listeners to be registered on a supposedly non-cancellable token and then trip the destructor assertion at thread exit. Prefer a single process-lifetime none object with a stable address (and ensure it is not destroyed during shutdown), or change the task API to hold the token by value/shared_ptr rather than by reference.
| static thread_local cancellation_source n{}; | |
| // Use a single process-lifetime instance with a stable address. | |
| // Allocated with new and intentionally never deleted to avoid | |
| // destruction order issues at shutdown. | |
| static cancellation& n = *new cancellation_source{}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cancellation.husesstd::system_error/std::errcandstd::mutex/std::lock_guardbut does not include the defining standard headers. It currently relies on transitive includes (e.g., fromticketed_collection.h), which makes this header non-self-contained and can break builds depending on include order. Add the direct includes (e.g.,<system_error>and<mutex>) here.