Reviewers: jarin,
https://codereview.chromium.org/1226143003/diff/1/src/d8.cc
File src/d8.cc (left):
https://codereview.chromium.org/1226143003/diff/1/src/d8.cc#oldcode2146
src/d8.cc:2146: static char s_buffer[128];
I'm pretty ashamed of this one... :-|
Description:
d8: Fix some TSAN bugs
* Fix embarrassing bug in DeserializeValue, using a static buffer in
multithreaded code.
* Fix thread leak when Worker.terminate() is not called.
[email protected]
Please review this at https://codereview.chromium.org/1226143003/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+54, -18 lines):
M src/d8.h
M src/d8.cc
Index: src/d8.cc
diff --git a/src/d8.cc b/src/d8.cc
index
0b737c6ffe291e6913269f0618d4608127fe5210..ecf790ff68c66d76da823b27690ff5c622c7132c
100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1609,6 +1609,7 @@ void
SerializationDataQueue::Enqueue(SerializationData* data) {
bool SerializationDataQueue::Dequeue(SerializationData** data) {
base::LockGuard<base::Mutex> lock_guard(&mutex_);
+ *data = NULL;
if (data_.is_empty()) return false;
*data = data_.Remove(0);
return true;
@@ -1662,7 +1663,9 @@ void Worker::PostMessage(SerializationData* data) {
SerializationData* Worker::GetMessage() {
SerializationData* data = NULL;
while (!out_queue_.Dequeue(&data)) {
- if (base::NoBarrier_Load(&state_) != RUNNING) break;
+ // If the worker is no longer running, and there are no messages in the
+ // queue, don't expect any more messages from it.
+ if (base::NoBarrier_Load(&state_) > RUNNING) break;
out_semaphore_.Wait();
}
@@ -1671,14 +1674,53 @@ SerializationData* Worker::GetMessage() {
void Worker::Terminate() {
- if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) ==
RUNNING) {
+ if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATING) ==
+ RUNNING) {
// Post NULL to wake the Worker thread message loop.
PostMessage(NULL);
- thread_->Join();
}
}
+void Worker::WaitForThread() {
+ Terminate();
+
+ State expected_state = TERMINATING;
+ while (true) {
+ State actual_state = static_cast<State>(
+ base::NoBarrier_CompareAndSwap(&state_, expected_state, JOINING));
+
+ if (actual_state == expected_state) break;
+
+ switch (actual_state) {
+ case IDLE:
+ case RUNNING:
+ // We terminated above, we should never be IDLE or RUNNING.
+ UNREACHABLE();
+ return;
+
+ case TERMINATING:
+ case STOPPED:
+ // Try again.
+ expected_state = actual_state;
+ break;
+
+ case JOINING:
+ // Someone else is joining. Bail.
+ return;
+
+ case JOINED:
+ // Tried to join twice.
+ UNREACHABLE();
+ return;
+ }
+ }
+
+ thread_->Join();
+ base::NoBarrier_Store(&state_, JOINED);
+}
+
+
void Worker::ExecuteInThread() {
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
@@ -1741,11 +1783,10 @@ void Worker::ExecuteInThread() {
}
isolate->Dispose();
- if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) ==
RUNNING) {
- // Post NULL to wake the thread waiting on GetMessage() if there is
one.
- out_queue_.Enqueue(NULL);
- out_semaphore_.Signal();
- }
+ base::NoBarrier_Store(&state_, STOPPED);
+ // Post NULL to wake the thread waiting on GetMessage() if there is one.
+ out_queue_.Enqueue(NULL);
+ out_semaphore_.Signal();
}
@@ -2143,18 +2184,12 @@ MaybeLocal<Value> Shell::DeserializeValue(Isolate*
isolate,
break;
case kSerializationTagString: {
int length = data.Read<int>(offset);
- static char s_buffer[128];
- char* p = s_buffer;
- bool allocated = false;
- if (length > static_cast<int>(sizeof(s_buffer))) {
- p = new char[length];
- allocated = true;
- }
+ char* p = new char[length];
data.ReadMemory(p, length, offset);
MaybeLocal<String> str =
String::NewFromUtf8(isolate, p, String::kNormalString, length);
if (!str.IsEmpty()) result = str.ToLocalChecked();
- if (allocated) delete[] p;
+ delete[] p;
break;
}
case kSerializationTagArray: {
@@ -2226,7 +2261,7 @@ void Shell::CleanupWorkers() {
for (int i = 0; i < workers_copy.length(); ++i) {
Worker* worker = workers_copy[i];
- worker->Terminate();
+ worker->WaitForThread();
delete worker;
}
Index: src/d8.h
diff --git a/src/d8.h b/src/d8.h
index
4d723473ea385c2c66b65c6ee65fd40e872592b8..f3b8eee783f87a92912735dc567df15621300146
100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -243,6 +243,7 @@ class Worker {
void PostMessage(SerializationData* data);
SerializationData* GetMessage();
void Terminate();
+ void WaitForThread();
private:
class WorkerThread : public base::Thread {
@@ -257,7 +258,7 @@ class Worker {
Worker* worker_;
};
- enum State { IDLE, RUNNING, TERMINATED };
+ enum State { IDLE, RUNNING, TERMINATING, STOPPED, JOINING, JOINED };
void ExecuteInThread();
void Cleanup();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.