From 2eef4e67165c38c147980ead785bcf7180b53009 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 8 Jan 2018 09:58:18 +0100 Subject: [PATCH] thread/Thread: add debug attribute "inside_handle" This attribute shall be used only for IsInside() to make this safe against a race condition described in #188: > There is no requirement on the implementation that the ID of the > created thread be available before the newly created thread starts > executing. http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_create.html): This means that on some pthread implementations (e.g. Haiku), the assert(thread.IsInside()) could fail. Closes #188 --- NEWS | 1 + src/thread/Thread.cxx | 4 ++++ src/thread/Thread.hxx | 12 +++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0f61a3aa7..f5182a945 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ ver 0.20.16 (not yet released) +* fix crash in debug build on Haiku and other operating systems ver 0.20.15 (2018/01/05) * queue: fix crash after seek failure diff --git a/src/thread/Thread.cxx b/src/thread/Thread.cxx index de3c46703..21aec1154 100644 --- a/src/thread/Thread.cxx +++ b/src/thread/Thread.cxx @@ -86,6 +86,10 @@ Thread::ThreadProc(void *ctx) { Thread &thread = *(Thread *)ctx; +#ifndef NDEBUG + thread.inside_handle = pthread_self(); +#endif + thread.Run(); return nullptr; diff --git a/src/thread/Thread.hxx b/src/thread/Thread.hxx index 797ae9676..45250c5c7 100644 --- a/src/thread/Thread.hxx +++ b/src/thread/Thread.hxx @@ -41,6 +41,16 @@ class Thread { DWORD id; #else pthread_t handle = pthread_t(); + +#ifndef NDEBUG + /** + * This handle is only used by IsInside(), and is set by the + * thread function. Since #handle is set by pthread_create() + * which is racy, we need this attribute for early checks + * inside the thread function. + */ + pthread_t inside_handle = pthread_t(); +#endif #endif public: @@ -79,7 +89,7 @@ public: default-constructed values" (comment from libstdc++) - and if both libstdc++ and libc++ get away with this, we can do it as well */ - return pthread_self() == handle; + return pthread_self() == inside_handle; #endif } #endif