Version 1.16.1
Cherry-pick 5f59a954f816ad0f46472eb4da05e714dbb7e117 to stable
Cherry-pick 18ec8dddd913398215747e7de3ecfb7f35c62e1c to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27d3383..b9d7fae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 1.16.1 - 2016-05-24
+
+Patch release, resolves one issue:
+
+* VM: Fixes a bug that caused intermittent hangs on Windows.
+(SDK issue [26400](https://github.com/dart-lang/sdk/issues/26400))
+
## 1.16.0 - 2016-04-26
### Core library changes
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index dfd4985..f125bb8 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -126,6 +126,7 @@
last_error_(NOERROR),
flags_(0),
read_thread_id_(Thread::kInvalidThreadId),
+ read_thread_handle_(NULL),
read_thread_starting_(false),
read_thread_finished_(false),
monitor_(new Monitor()) {
@@ -188,8 +189,7 @@
void Handle::WaitForReadThreadFinished() {
- // Join the Reader thread if there is one.
- ThreadId to_join = Thread::kInvalidThreadId;
+ HANDLE to_join = NULL;
{
MonitorLocker ml(monitor_);
if (read_thread_id_ != Thread::kInvalidThreadId) {
@@ -197,12 +197,16 @@
ml.Wait();
}
read_thread_finished_ = false;
- to_join = read_thread_id_;
read_thread_id_ = Thread::kInvalidThreadId;
+ to_join = read_thread_handle_;
+ read_thread_handle_ = NULL;
}
}
- if (to_join != Thread::kInvalidThreadId) {
- Thread::Join(to_join);
+ if (to_join != NULL) {
+ // Join the read thread.
+ DWORD res = WaitForSingleObject(to_join, INFINITE);
+ CloseHandle(to_join);
+ ASSERT(res == WAIT_OBJECT_0);
}
}
@@ -250,10 +254,12 @@
ASSERT(read_thread_starting_);
ASSERT(read_thread_id_ == Thread::kInvalidThreadId);
read_thread_id_ = Thread::GetCurrentThreadId();
+ read_thread_handle_ = OpenThread(SYNCHRONIZE, false, read_thread_id_);
read_thread_starting_ = false;
ml.Notify();
}
+
void Handle::NotifyReadThreadFinished() {
MonitorLocker ml(monitor_);
ASSERT(!read_thread_finished_);
@@ -750,6 +756,7 @@
MonitorLocker ml(monitor_);
write_thread_running_ = true;
thread_id_ = Thread::GetCurrentThreadId();
+ thread_handle_ = OpenThread(SYNCHRONIZE, false, thread_id_);
// Notify we have started.
ml.Notify();
@@ -839,7 +846,10 @@
while (write_thread_exists_) {
ml.Wait(Monitor::kNoTimeout);
}
- Thread::Join(thread_id_);
+ // Join the thread.
+ DWORD res = WaitForSingleObject(thread_handle_, INFINITE);
+ CloseHandle(thread_handle_);
+ ASSERT(res == WAIT_OBJECT_0);
}
Handle::DoClose();
}
@@ -1366,6 +1376,7 @@
EventHandlerImplementation::EventHandlerImplementation() {
startup_monitor_ = new Monitor();
handler_thread_id_ = Thread::kInvalidThreadId;
+ handler_thread_handle_ = NULL;
completion_port_ =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
if (completion_port_ == NULL) {
@@ -1376,7 +1387,10 @@
EventHandlerImplementation::~EventHandlerImplementation() {
- Thread::Join(handler_thread_id_);
+ // Join the handler thread.
+ DWORD res = WaitForSingleObject(handler_thread_handle_, INFINITE);
+ CloseHandle(handler_thread_handle_);
+ ASSERT(res == WAIT_OBJECT_0);
delete startup_monitor_;
CloseHandle(completion_port_);
}
@@ -1415,6 +1429,8 @@
{
MonitorLocker ml(handler_impl->startup_monitor_);
handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId();
+ handler_impl->handler_thread_handle_ =
+ OpenThread(SYNCHRONIZE, false, handler_impl->handler_thread_id_);
ml.Notify();
}
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index edb5c48..9daff93 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -263,6 +263,7 @@
DWORD last_error_;
ThreadId read_thread_id_;
+ HANDLE read_thread_handle_;
bool read_thread_starting_;
bool read_thread_finished_;
@@ -298,6 +299,7 @@
explicit StdHandle(HANDLE handle)
: FileHandle(handle),
thread_id_(Thread::kInvalidThreadId),
+ thread_handle_(NULL),
thread_wrote_(0),
write_thread_exists_(false),
write_thread_running_(false) {
@@ -312,6 +314,7 @@
private:
ThreadId thread_id_;
+ HANDLE thread_handle_;
intptr_t thread_wrote_;
bool write_thread_exists_;
bool write_thread_running_;
@@ -538,6 +541,7 @@
Monitor* startup_monitor_;
ThreadId handler_thread_id_;
+ HANDLE handler_thread_handle_;
TimeoutQueue timeout_queue_; // Time for next timeout.
bool shutdown_;
diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h
index d95675d..979c77f 100644
--- a/runtime/bin/thread.h
+++ b/runtime/bin/thread.h
@@ -51,7 +51,6 @@
static void SetThreadLocal(ThreadLocalKey key, uword value);
static intptr_t GetMaxStackSize();
static ThreadId GetCurrentThreadId();
- static bool Join(ThreadId id);
static intptr_t ThreadIdToIntPtr(ThreadId id);
static bool Compare(ThreadId a, ThreadId b);
static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage);
diff --git a/runtime/bin/thread_android.cc b/runtime/bin/thread_android.cc
index 4f5c547..ce27ea3 100644
--- a/runtime/bin/thread_android.cc
+++ b/runtime/bin/thread_android.cc
@@ -155,11 +155,6 @@
}
-bool Thread::Join(ThreadId id) {
- return false;
-}
-
-
intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
ASSERT(sizeof(id) == sizeof(intptr_t));
return static_cast<intptr_t>(id);
diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc
index 7a2a92a..6ea923e 100644
--- a/runtime/bin/thread_linux.cc
+++ b/runtime/bin/thread_linux.cc
@@ -156,11 +156,6 @@
}
-bool Thread::Join(ThreadId id) {
- return false;
-}
-
-
intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
ASSERT(sizeof(id) == sizeof(intptr_t));
return static_cast<intptr_t>(id);
diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc
index 8286835..9477e8ab 100644
--- a/runtime/bin/thread_macos.cc
+++ b/runtime/bin/thread_macos.cc
@@ -148,11 +148,6 @@
}
-bool Thread::Join(ThreadId id) {
- return false;
-}
-
-
intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
ASSERT(sizeof(id) == sizeof(intptr_t));
return reinterpret_cast<intptr_t>(id);
diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc
index db41196..92a9801 100644
--- a/runtime/bin/thread_win.cc
+++ b/runtime/bin/thread_win.cc
@@ -103,27 +103,6 @@
}
-bool Thread::Join(ThreadId id) {
- HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
-
- // TODO(zra): OSThread::Start() closes the handle to the thread. Thus, by the
- // time we try to join the thread, its resources may have already been
- // reclaimed, and joining will fail. This can be avoided in a couple of ways.
- // First, GetCurrentThreadJoinId could call OpenThread and return a handle.
- // This is bad, because each of those handles would have to be closed.
- // Second OSThread could be refactored to no longer be AllStatic. Then the
- // handle could be cached in the object by the Start method.
- if (handle == NULL) {
- return false;
- }
-
- DWORD res = WaitForSingleObject(handle, INFINITE);
- CloseHandle(handle);
- ASSERT(res == WAIT_OBJECT_0);
- return true;
-}
-
-
intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
ASSERT(sizeof(id) <= sizeof(intptr_t));
return static_cast<intptr_t>(id);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 02c28db..aa77c40 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -9714,8 +9714,7 @@
GlobalTimelineThreadData()
: monitor_(new Monitor()),
data_(new AppendData()),
- running_(true),
- join_id_(OSThread::kInvalidThreadJoinId) {
+ running_(true) {
}
~GlobalTimelineThreadData() {
@@ -9733,16 +9732,13 @@
AppendData* data() const { return data_; }
uint8_t* buffer() const { return data_->buffer; }
intptr_t buffer_length() const { return data_->buffer_length; }
- ThreadJoinId join_id() const { return join_id_; }
void set_running(bool running) { running_ = running; }
- void set_join_id(ThreadJoinId join_id) { join_id_ = join_id; }
private:
Monitor* monitor_;
AppendData* data_;
bool running_;
- ThreadJoinId join_id_;
};
@@ -9758,7 +9754,6 @@
Dart_GlobalTimelineGetTrace(AppendStreamConsumer, data->data());
EXPECT(success);
data->set_running(false);
- data->set_join_id(OSThread::Current()->join_id());
ml.Notify();
}
}
@@ -9805,7 +9800,6 @@
}
buffer = reinterpret_cast<char*>(data.buffer());
buffer_length = data.buffer_length();
- OSThread::Join(data.join_id());
}
EXPECT(buffer_length > 0);
EXPECT(buffer != NULL);
@@ -9847,7 +9841,6 @@
}
buffer = reinterpret_cast<char*>(data2.buffer());
buffer_length = data2.buffer_length();
- OSThread::Join(data2.join_id());
}
EXPECT(buffer_length > 0);
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 947b7f6..75a7a31 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -23,7 +23,9 @@
OSThread::OSThread() :
BaseThread(true),
id_(OSThread::GetCurrentThreadId()),
- join_id_(OSThread::GetCurrentThreadJoinId()),
+#if defined(DEBUG)
+ join_id_(kInvalidThreadJoinId),
+#endif
trace_id_(OSThread::GetCurrentThreadTraceId()),
name_(NULL),
timeline_block_lock_(new Mutex()),
@@ -160,8 +162,8 @@
}
-bool OSThread::IsThreadInList(ThreadJoinId join_id) {
- if (join_id == OSThread::kInvalidThreadJoinId) {
+bool OSThread::IsThreadInList(ThreadId id) {
+ if (id == OSThread::kInvalidThreadId) {
return false;
}
OSThreadIterator it;
@@ -169,8 +171,8 @@
ASSERT(OSThread::thread_list_lock_->IsOwnedByCurrentThread());
OSThread* t = it.Next();
// An address test is not sufficient because the allocator may recycle
- // the address for another Thread. Test against the thread's join id.
- if (t->join_id() == join_id) {
+ // the address for another Thread. Test against the thread's id.
+ if (t->id() == id) {
return true;
}
}
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index e0b41ac..19f340d 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -61,13 +61,8 @@
return id_;
}
- ThreadJoinId join_id() const {
- ASSERT(join_id_ != OSThread::kInvalidThreadJoinId);
- return join_id_;
- }
-
ThreadId trace_id() const {
- ASSERT(trace_id_ != OSThread::kInvalidThreadJoinId);
+ ASSERT(trace_id_ != OSThread::kInvalidThreadId);
return trace_id_;
}
@@ -175,10 +170,14 @@
static bool Compare(ThreadId a, ThreadId b);
static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage);
+ // This function can be called only once per OSThread, and should only be
+ // called when the retunred id will eventually be passed to OSThread::Join().
+ static ThreadJoinId GetCurrentThreadJoinId(OSThread* thread);
+
// Called at VM startup and shutdown.
static void InitOnce();
- static bool IsThreadInList(ThreadJoinId join_id);
+ static bool IsThreadInList(ThreadId id);
static void DisableOSThreadCreation();
static void EnableOSThreadCreation();
@@ -206,7 +205,6 @@
static void Cleanup();
static ThreadId GetCurrentThreadTraceId();
- static ThreadJoinId GetCurrentThreadJoinId();
static OSThread* GetOSThreadFromThread(Thread* thread);
static void AddThreadToListLocked(OSThread* thread);
static void RemoveThreadFromList(OSThread* thread);
@@ -215,7 +213,11 @@
static ThreadLocalKey thread_key_;
const ThreadId id_;
- const ThreadJoinId join_id_;
+#if defined(DEBUG)
+ // In DEBUG mode we use this field to ensure that GetCurrentThreadJoinId is
+ // only called once per OSThread.
+ ThreadJoinId join_id_;
+#endif
const ThreadId trace_id_; // Used to interface with tracing tools.
char* name_; // A name for this thread.
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 9b93cbe..fab6d12 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -175,8 +175,17 @@
}
-ThreadJoinId OSThread::GetCurrentThreadJoinId() {
- return pthread_self();
+ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) {
+ ASSERT(thread != NULL);
+ // Make sure we're filling in the join id for the current thread.
+ ASSERT(thread->id() == GetCurrentThreadId());
+ // Make sure the join_id_ hasn't been set, yet.
+ DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId);
+ pthread_t id = pthread_self();
+#if defined(DEBUG)
+ thread->join_id_ = id;
+#endif
+ return id;
}
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index a0e68f1..5bc8e8b 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -177,8 +177,17 @@
}
-ThreadJoinId OSThread::GetCurrentThreadJoinId() {
- return pthread_self();
+ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) {
+ ASSERT(thread != NULL);
+ // Make sure we're filling in the join id for the current thread.
+ ASSERT(thread->id() == GetCurrentThreadId());
+ // Make sure the join_id_ hasn't been set, yet.
+ DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId);
+ pthread_t id = pthread_self();
+#if defined(DEBUG)
+ thread->join_id_ = id;
+#endif
+ return id;
}
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 42dd360..20d1f2b 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -168,8 +168,17 @@
}
-ThreadJoinId OSThread::GetCurrentThreadJoinId() {
- return pthread_self();
+ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) {
+ ASSERT(thread != NULL);
+ // Make sure we're filling in the join id for the current thread.
+ ASSERT(thread->id() == GetCurrentThreadId());
+ // Make sure the join_id_ hasn't been set, yet.
+ DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId);
+ pthread_t id = pthread_self();
+#if defined(DEBUG)
+ thread->join_id_ = id;
+#endif
+ return id;
}
diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc
index 9d282bc..4cbef14 100644
--- a/runtime/vm/os_thread_win.cc
+++ b/runtime/vm/os_thread_win.cc
@@ -91,7 +91,7 @@
const ThreadId OSThread::kInvalidThreadId = 0;
-const ThreadJoinId OSThread::kInvalidThreadJoinId = 0;
+const ThreadJoinId OSThread::kInvalidThreadJoinId = NULL;
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
@@ -130,27 +130,25 @@
}
-ThreadJoinId OSThread::GetCurrentThreadJoinId() {
- // TODO(zra): Use the thread handle as the join id in order to have a more
- // reliable join on windows.
- return ::GetCurrentThreadId();
+ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) {
+ ASSERT(thread != NULL);
+ // Make sure we're filling in the join id for the current thread.
+ ThreadId id = GetCurrentThreadId();
+ ASSERT(thread->id() == id);
+ // Make sure the join_id_ hasn't been set, yet.
+ DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId);
+ HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
+ ASSERT(handle != NULL);
+#if defined(DEBUG)
+ thread->join_id_ = handle;
+#endif
+ return handle;
}
void OSThread::Join(ThreadJoinId id) {
- HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
-
- // TODO(zra): OSThread::Start() closes the handle to the thread. Thus, by the
- // time we try to join the thread, its resources may have already been
- // reclaimed, and joining will fail. This can be avoided in a couple of ways.
- // First, GetCurrentThreadJoinId could call OpenThread and return a handle.
- // This is bad, because each of those handles would have to be closed.
- // Second OSThread could be refactored to no longer be AllStatic. Then the
- // handle could be cached in the object by the Start method.
- if (handle == NULL) {
- return;
- }
-
+ HANDLE handle = static_cast<HANDLE>(id);
+ ASSERT(handle != NULL);
DWORD res = WaitForSingleObject(handle, INFINITE);
CloseHandle(handle);
ASSERT(res == WAIT_OBJECT_0);
diff --git a/runtime/vm/os_thread_win.h b/runtime/vm/os_thread_win.h
index 790306d..913b074 100644
--- a/runtime/vm/os_thread_win.h
+++ b/runtime/vm/os_thread_win.h
@@ -18,7 +18,7 @@
typedef DWORD ThreadLocalKey;
typedef DWORD ThreadId;
-typedef DWORD ThreadJoinId;
+typedef HANDLE ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index 1e0d8cf..fa14d2e 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -157,7 +157,7 @@
MonitorLocker startup_ml(monitor_);
OSThread* os_thread = OSThread::Current();
ASSERT(os_thread != NULL);
- interrupter_thread_id_ = os_thread->join_id();
+ interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId(os_thread);
thread_running_ = true;
startup_ml.Notify();
}
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index fb0f7d7..0c326d3 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -212,6 +212,16 @@
}
+void ThreadPool::SetIdleLocked(Worker* worker) {
+ ASSERT(mutex_.IsOwnedByCurrentThread());
+ ASSERT(worker->owned_ && !IsIdle(worker));
+ worker->idle_next_ = idle_workers_;
+ idle_workers_ = worker;
+ count_idle_++;
+ count_running_--;
+}
+
+
void ThreadPool::SetIdleAndReapExited(Worker* worker) {
JoinList* list = NULL;
{
@@ -219,17 +229,25 @@
if (shutting_down_) {
return;
}
- ASSERT(worker->owned_ && !IsIdle(worker));
- worker->idle_next_ = idle_workers_;
- idle_workers_ = worker;
- count_idle_++;
- count_running_--;
-
- // While we have the lock, opportunistically grab and clear the join_list_.
+ if (join_list_ == NULL) {
+ // Nothing to join, add to the idle list and return.
+ SetIdleLocked(worker);
+ return;
+ }
+ // There is something to join. Grab the join list, drop the lock, do the
+ // join, then grab the lock again and add to the idle list.
list = join_list_;
join_list_ = NULL;
}
JoinList::Join(&list);
+
+ {
+ MutexLocker ml(&mutex_);
+ if (shutting_down_) {
+ return;
+ }
+ SetIdleLocked(worker);
+ }
}
@@ -250,7 +268,8 @@
// so that we can join on it at the next opportunity.
OSThread* os_thread = OSThread::Current();
ASSERT(os_thread != NULL);
- JoinList::AddLocked(os_thread->join_id(), &join_list_);
+ ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread);
+ JoinList::AddLocked(join_id, &join_list_);
count_stopped_++;
count_idle_--;
return true;
@@ -430,7 +449,6 @@
OSThread* os_thread = OSThread::Current();
ASSERT(os_thread != NULL);
ThreadId id = os_thread->id();
- ThreadJoinId join_id = os_thread->join_id();
ThreadPool* pool;
// Set the thread's stack_base based on the current stack pointer.
@@ -454,6 +472,7 @@
// Inform the thread pool that we are exiting. We remove this worker from
// shutting_down_workers_ list because there will be no need for the
// ThreadPool to take action for this worker.
+ ThreadJoinId join_id = OSThread::GetCurrentThreadJoinId(os_thread);
{
MutexLocker ml(&pool->mutex_);
JoinList::AddLocked(join_id, &pool->join_list_);
diff --git a/runtime/vm/thread_pool.h b/runtime/vm/thread_pool.h
index 1713781..8cd29a2 100644
--- a/runtime/vm/thread_pool.h
+++ b/runtime/vm/thread_pool.h
@@ -125,6 +125,7 @@
void ReapExitedIdleThreads();
// Worker operations.
+ void SetIdleLocked(Worker* worker); // Assumes mutex_ is held.
void SetIdleAndReapExited(Worker* worker);
bool ReleaseIdleWorker(Worker* worker);
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index aa006df..d0deba9 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -435,12 +435,13 @@
VM_TEST_CASE(ThreadIterator_FindSelf) {
OSThread* current = OSThread::Current();
- EXPECT(OSThread::IsThreadInList(current->join_id()));
+ EXPECT(OSThread::IsThreadInList(current->id()));
}
struct ThreadIteratorTestParams {
- ThreadId spawned_thread_join_id;
+ ThreadId spawned_thread_id;
+ ThreadJoinId spawned_thread_join_id;
Monitor* monitor;
};
@@ -452,9 +453,10 @@
EXPECT(thread != NULL);
MonitorLocker ml(params->monitor);
- params->spawned_thread_join_id = thread->join_id();
- EXPECT(params->spawned_thread_join_id != OSThread::kInvalidThreadJoinId);
- EXPECT(OSThread::IsThreadInList(thread->join_id()));
+ params->spawned_thread_id = thread->id();
+ params->spawned_thread_join_id = OSThread::GetCurrentThreadJoinId(thread);
+ EXPECT(params->spawned_thread_id != OSThread::kInvalidThreadId);
+ EXPECT(OSThread::IsThreadInList(thread->id()));
ml.Notify();
}
@@ -463,25 +465,25 @@
// on Windows. See |OnDartThreadExit| in os_thread_win.cc for more details.
TEST_CASE(ThreadIterator_AddFindRemove) {
ThreadIteratorTestParams params;
- params.spawned_thread_join_id = OSThread::kInvalidThreadJoinId;
+ params.spawned_thread_id = OSThread::kInvalidThreadId;
params.monitor = new Monitor();
{
MonitorLocker ml(params.monitor);
- EXPECT(params.spawned_thread_join_id == OSThread::kInvalidThreadJoinId);
- // Spawn thread and wait to receive the thread join id.
+ EXPECT(params.spawned_thread_id == OSThread::kInvalidThreadId);
+ // Spawn thread and wait to receive the thread id.
OSThread::Start("ThreadIteratorTest",
ThreadIteratorTestMain,
reinterpret_cast<uword>(¶ms));
- while (params.spawned_thread_join_id == OSThread::kInvalidThreadJoinId) {
+ while (params.spawned_thread_id == OSThread::kInvalidThreadId) {
ml.Wait();
}
+ EXPECT(params.spawned_thread_id != OSThread::kInvalidThreadId);
EXPECT(params.spawned_thread_join_id != OSThread::kInvalidThreadJoinId);
- // Join thread.
OSThread::Join(params.spawned_thread_join_id);
}
- EXPECT(!OSThread::IsThreadInList(params.spawned_thread_join_id))
+ EXPECT(!OSThread::IsThreadInList(params.spawned_thread_id))
delete params.monitor;
}
diff --git a/tools/VERSION b/tools/VERSION
index 5f18786..43b3e89 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
CHANNEL stable
MAJOR 1
MINOR 16
-PATCH 0
+PATCH 1
PRERELEASE 0
PRERELEASE_PATCH 0