 Chromium Code Reviews
 Chromium Code Reviews Issue 1226143003:
  d8: Fix some TSAN bugs  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1226143003:
  d8: Fix some TSAN bugs  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| 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: | 
| 
Jarin
2015/07/10 10:43:17
Why do we want to retry when STOPPED?
Actually, I
 
binji
2015/07/10 17:40:46
You're right, this is too complicated. I refactore
 | 
| + // Try again. | 
| + expected_state = actual_state; | 
| + break; | 
| + | 
| + case JOINING: | 
| 
Jarin
2015/07/10 10:43:17
Is not this only called when the shell finishes, s
 
binji
2015/07/10 17:40:46
True, this was just caution to prevent multiple jo
 | 
| + // 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]; | 
| 
binji
2015/07/09 00:13:12
I'm pretty ashamed of this one... :-|
 | 
| - 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]; | 
| 
Jarin
2015/07/10 10:43:17
How about using std::vector<char> here, instead of
 
binji
2015/07/10 17:40:46
Done (though I was not sure that std containers we
 | 
| 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; | 
| } |