This is an automated email from the ASF dual-hosted git repository. guangmingchen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push: new d95ede52 Bugfix: Butex returned to ObjectPool triggers use-after-poison (#3012) d95ede52 is described below commit d95ede52bd9fb01817162a50c5ba3c520ecdac1e Author: Bright Chen <chenguangmin...@foxmail.com> AuthorDate: Tue Jul 15 14:05:42 2025 +0800 Bugfix: Butex returned to ObjectPool triggers use-after-poison (#3012) --- docs/cn/sanitizers.md | 18 ++++++++++++++++++ src/bthread/butex.cpp | 11 +++++++++++ src/bthread/execution_queue_inl.h | 2 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/cn/sanitizers.md b/docs/cn/sanitizers.md index 30135269..bdd32010 100644 --- a/docs/cn/sanitizers.md +++ b/docs/cn/sanitizers.md @@ -17,6 +17,24 @@ BUTIL_ASAN_POISON_MEMORY_REGION(addr, size); BUTIL_ASAN_UNPOISON_MEMORY_REGION(addr, size); ``` +如果某些对象池在设计上允许操作对象池中的对象,例如ExecutionQueue、Butex,则需要特化ObjectPoolWithASanPoison,表示不对这些对象池的对象内存进行poison/unpoison,例如: + +```c++ +namespace butil { +// TaskNode::cancel() may access the TaskNode object returned to the ObjectPool<TaskNode>, +// so ObjectPool<TaskNode> can not poison the memory region of TaskNode. +template <> +struct ObjectPoolWithASanPoison<bthread::TaskNode> : false_type {}; +} // namespace butil + +namespace butil { +// Butex object returned to the ObjectPool<Butex> may be accessed, +// so ObjectPool<Butex> can not poison the memory region of Butex. +template <> +struct ObjectPoolWithASanPoison<bthread::Butex> : false_type {}; +} // namespace butil +``` + 其他问题:如果ASan报告中new/delete的调用栈不完整,可以通过设置`fast_unwind_on_malloc=0`回溯出完整的调用栈了。需要注意的是`fast_unwind_on_malloc=0`很耗性能。 ## ThreadSanitizer(TSan) diff --git a/src/bthread/butex.cpp b/src/bthread/butex.cpp index c54198c6..aca12816 100644 --- a/src/bthread/butex.cpp +++ b/src/bthread/butex.cpp @@ -122,6 +122,17 @@ struct BAIDU_CACHELINE_ALIGNMENT Butex { BAIDU_CASSERT(offsetof(Butex, value) == 0, offsetof_value_must_0); BAIDU_CASSERT(sizeof(Butex) == BAIDU_CACHELINE_SIZE, butex_fits_in_one_cacheline); +} // namespace bthread + +namespace butil { +// Butex object returned to the ObjectPool<Butex> may be accessed, +// so ObjectPool<Butex> can not poison the memory region of Butex. +template <> +struct ObjectPoolWithASanPoison<bthread::Butex> : false_type {}; +} // namespace butil + +namespace bthread { + static void wakeup_pthread(ButexPthreadWaiter* pw) { // release fence makes wait_pthread see changes before wakeup. pw->sig.store(PTHREAD_SIGNALLED, butil::memory_order_release); diff --git a/src/bthread/execution_queue_inl.h b/src/bthread/execution_queue_inl.h index cf7d2ee5..ddf7bc6b 100644 --- a/src/bthread/execution_queue_inl.h +++ b/src/bthread/execution_queue_inl.h @@ -587,7 +587,7 @@ inline int ExecutionQueueBase::dereference() { } // namespace bthread namespace butil { -// `TaskNode::cancel' may access the TaskNode object returned to the ObjectPool<TaskNode>, +// TaskNode::cancel() may access the TaskNode object returned to the ObjectPool<TaskNode>, // so ObjectPool<TaskNode> can not poison the memory region of TaskNode. template <> struct ObjectPoolWithASanPoison<bthread::TaskNode> : false_type {}; --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@brpc.apache.org For additional commands, e-mail: dev-h...@brpc.apache.org