Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(699)

Side by Side Diff: src/d8.cc

Issue 1255563002: [d8 Workers] Fix bug creating Worker during main thread termination (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: . Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/regress/regress-crbug-511880.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 // Defined when linking against shared lib on Windows. 6 // Defined when linking against shared lib on Windows.
7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED) 7 #if defined(USING_V8_SHARED) && !defined(V8_SHARED)
8 #define V8_SHARED 8 #define V8_SHARED
9 #endif 9 #endif
10 10
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) { 724 void Shell::WorkerNew(const v8::FunctionCallbackInfo<v8::Value>& args) {
725 Isolate* isolate = args.GetIsolate(); 725 Isolate* isolate = args.GetIsolate();
726 HandleScope handle_scope(isolate); 726 HandleScope handle_scope(isolate);
727 if (args.Length() < 1 || !args[0]->IsString()) { 727 if (args.Length() < 1 || !args[0]->IsString()) {
728 Throw(args.GetIsolate(), "1st argument must be string"); 728 Throw(args.GetIsolate(), "1st argument must be string");
729 return; 729 return;
730 } 730 }
731 731
732 { 732 {
733 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer()); 733 base::LockGuard<base::Mutex> lock_guard(workers_mutex_.Pointer());
734 // Intialize the internal field to NULL; if we return early without
735 // creating a new Worker (because the main thread is terminating) we can
736 // early-out from the instance calls.
737 args.Holder()->SetAlignedPointerInInternalField(0, NULL);
738
734 if (!allow_new_workers_) return; 739 if (!allow_new_workers_) return;
735 740
736 Worker* worker = new Worker; 741 Worker* worker = new Worker;
737 args.This()->SetInternalField(0, External::New(isolate, worker)); 742 args.Holder()->SetAlignedPointerInInternalField(0, worker);
738 workers_.Add(worker); 743 workers_.Add(worker);
739 744
740 String::Utf8Value script(args[0]); 745 String::Utf8Value script(args[0]);
741 if (!*script) { 746 if (!*script) {
742 Throw(args.GetIsolate(), "Can't get worker script"); 747 Throw(args.GetIsolate(), "Can't get worker script");
743 return; 748 return;
744 } 749 }
745 worker->StartExecuteInThread(isolate, *script); 750 worker->StartExecuteInThread(isolate, *script);
746 } 751 }
747 } 752 }
748 753
749 754
750 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 755 void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
751 Isolate* isolate = args.GetIsolate(); 756 Isolate* isolate = args.GetIsolate();
752 HandleScope handle_scope(isolate); 757 HandleScope handle_scope(isolate);
753 Local<Context> context = isolate->GetCurrentContext(); 758 Local<Context> context = isolate->GetCurrentContext();
754 Local<Value> this_value;
755 759
756 if (args.Length() < 1) { 760 if (args.Length() < 1) {
757 Throw(isolate, "Invalid argument"); 761 Throw(isolate, "Invalid argument");
758 return; 762 return;
759 } 763 }
760 764
761 if (args.This()->InternalFieldCount() > 0) { 765 if (args.Holder()->InternalFieldCount() <= 0) {
762 this_value = args.This()->GetInternalField(0);
763 }
764 if (this_value.IsEmpty()) {
765 Throw(isolate, "this is not a Worker"); 766 Throw(isolate, "this is not a Worker");
766 return; 767 return;
767 } 768 }
768 769
769 Worker* worker = 770 Worker* worker = static_cast<Worker*>(
770 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 771 args.Holder()->GetAlignedPointerFromInternalField(0));
772 if (worker == NULL) {
773 Throw(isolate, "Worker is defunct because main thread is terminating");
774 return;
775 }
771 776
772 Local<Value> message = args[0]; 777 Local<Value> message = args[0];
773 ObjectList to_transfer; 778 ObjectList to_transfer;
774 if (args.Length() >= 2) { 779 if (args.Length() >= 2) {
775 if (!args[1]->IsArray()) { 780 if (!args[1]->IsArray()) {
776 Throw(isolate, "Transfer list must be an Array"); 781 Throw(isolate, "Transfer list must be an Array");
777 return; 782 return;
778 } 783 }
779 784
780 Local<Array> transfer = Local<Array>::Cast(args[1]); 785 Local<Array> transfer = Local<Array>::Cast(args[1]);
(...skipping 19 matching lines...) Expand all
800 worker->PostMessage(data); 805 worker->PostMessage(data);
801 } else { 806 } else {
802 delete data; 807 delete data;
803 } 808 }
804 } 809 }
805 810
806 811
807 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 812 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
808 Isolate* isolate = args.GetIsolate(); 813 Isolate* isolate = args.GetIsolate();
809 HandleScope handle_scope(isolate); 814 HandleScope handle_scope(isolate);
810 Local<Value> this_value; 815 if (args.Holder()->InternalFieldCount() <= 0) {
811 if (args.This()->InternalFieldCount() > 0) {
812 this_value = args.This()->GetInternalField(0);
813 }
814 if (this_value.IsEmpty()) {
815 Throw(isolate, "this is not a Worker"); 816 Throw(isolate, "this is not a Worker");
816 return; 817 return;
817 } 818 }
818 819
819 Worker* worker = 820 Worker* worker = static_cast<Worker*>(
820 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 821 args.Holder()->GetAlignedPointerFromInternalField(0));
822 if (worker == NULL) {
823 Throw(isolate, "Worker is defunct because main thread is terminating");
824 return;
825 }
821 826
822 SerializationData* data = worker->GetMessage(); 827 SerializationData* data = worker->GetMessage();
823 if (data) { 828 if (data) {
824 int offset = 0; 829 int offset = 0;
825 Local<Value> data_value; 830 Local<Value> data_value;
826 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) { 831 if (Shell::DeserializeValue(isolate, *data, &offset).ToLocal(&data_value)) {
827 args.GetReturnValue().Set(data_value); 832 args.GetReturnValue().Set(data_value);
828 } 833 }
829 delete data; 834 delete data;
830 } 835 }
831 } 836 }
832 837
833 838
834 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { 839 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
835 Isolate* isolate = args.GetIsolate(); 840 Isolate* isolate = args.GetIsolate();
836 HandleScope handle_scope(isolate); 841 HandleScope handle_scope(isolate);
837 Local<Value> this_value; 842 if (args.Holder()->InternalFieldCount() <= 0) {
838 if (args.This()->InternalFieldCount() > 0) {
839 this_value = args.This()->GetInternalField(0);
840 }
841 if (this_value.IsEmpty()) {
842 Throw(isolate, "this is not a Worker"); 843 Throw(isolate, "this is not a Worker");
843 return; 844 return;
844 } 845 }
845 846
846 Worker* worker = 847 Worker* worker = static_cast<Worker*>(
847 static_cast<Worker*>(Local<External>::Cast(this_value)->Value()); 848 args.Holder()->GetAlignedPointerFromInternalField(0));
849 if (worker == NULL) {
850 Throw(isolate, "Worker is defunct because main thread is terminating");
851 return;
852 }
853
848 worker->Terminate(); 854 worker->Terminate();
849 } 855 }
850 #endif // !V8_SHARED 856 #endif // !V8_SHARED
851 857
852 858
853 void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) { 859 void Shell::QuitOnce(v8::FunctionCallbackInfo<v8::Value>* args) {
854 int exit_code = (*args)[0] 860 int exit_code = (*args)[0]
855 ->Int32Value(args->GetIsolate()->GetCurrentContext()) 861 ->Int32Value(args->GetIsolate()->GetCurrentContext())
856 .FromMaybe(0); 862 .FromMaybe(0);
857 #ifndef V8_SHARED 863 #ifndef V8_SHARED
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 String::NewFromUtf8(isolate, "now", NewStringType::kNormal) 1258 String::NewFromUtf8(isolate, "now", NewStringType::kNormal)
1253 .ToLocalChecked(), 1259 .ToLocalChecked(),
1254 FunctionTemplate::New(isolate, PerformanceNow)); 1260 FunctionTemplate::New(isolate, PerformanceNow));
1255 global_template->Set( 1261 global_template->Set(
1256 String::NewFromUtf8(isolate, "performance", NewStringType::kNormal) 1262 String::NewFromUtf8(isolate, "performance", NewStringType::kNormal)
1257 .ToLocalChecked(), 1263 .ToLocalChecked(),
1258 performance_template); 1264 performance_template);
1259 1265
1260 Local<FunctionTemplate> worker_fun_template = 1266 Local<FunctionTemplate> worker_fun_template =
1261 FunctionTemplate::New(isolate, WorkerNew); 1267 FunctionTemplate::New(isolate, WorkerNew);
1268 Local<Signature> worker_signature =
1269 Signature::New(isolate, worker_fun_template);
1270 worker_fun_template->SetClassName(
1271 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
1272 .ToLocalChecked());
1262 worker_fun_template->PrototypeTemplate()->Set( 1273 worker_fun_template->PrototypeTemplate()->Set(
1263 String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal) 1274 String::NewFromUtf8(isolate, "terminate", NewStringType::kNormal)
1264 .ToLocalChecked(), 1275 .ToLocalChecked(),
1265 FunctionTemplate::New(isolate, WorkerTerminate)); 1276 FunctionTemplate::New(isolate, WorkerTerminate, Local<Value>(),
1277 worker_signature));
1266 worker_fun_template->PrototypeTemplate()->Set( 1278 worker_fun_template->PrototypeTemplate()->Set(
1267 String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal) 1279 String::NewFromUtf8(isolate, "postMessage", NewStringType::kNormal)
1268 .ToLocalChecked(), 1280 .ToLocalChecked(),
1269 FunctionTemplate::New(isolate, WorkerPostMessage)); 1281 FunctionTemplate::New(isolate, WorkerPostMessage, Local<Value>(),
1282 worker_signature));
1270 worker_fun_template->PrototypeTemplate()->Set( 1283 worker_fun_template->PrototypeTemplate()->Set(
1271 String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal) 1284 String::NewFromUtf8(isolate, "getMessage", NewStringType::kNormal)
1272 .ToLocalChecked(), 1285 .ToLocalChecked(),
1273 FunctionTemplate::New(isolate, WorkerGetMessage)); 1286 FunctionTemplate::New(isolate, WorkerGetMessage, Local<Value>(),
1287 worker_signature));
1274 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1); 1288 worker_fun_template->InstanceTemplate()->SetInternalFieldCount(1);
1275 global_template->Set( 1289 global_template->Set(
1276 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal) 1290 String::NewFromUtf8(isolate, "Worker", NewStringType::kNormal)
1277 .ToLocalChecked(), 1291 .ToLocalChecked(),
1278 worker_fun_template); 1292 worker_fun_template);
1279 #endif // !V8_SHARED 1293 #endif // !V8_SHARED
1280 1294
1281 Local<ObjectTemplate> os_templ = ObjectTemplate::New(isolate); 1295 Local<ObjectTemplate> os_templ = ObjectTemplate::New(isolate);
1282 AddOSMethods(isolate, os_templ); 1296 AddOSMethods(isolate, os_templ);
1283 global_template->Set( 1297 global_template->Set(
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 } 1789 }
1776 data_.Clear(); 1790 data_.Clear();
1777 } 1791 }
1778 1792
1779 1793
1780 Worker::Worker() 1794 Worker::Worker()
1781 : in_semaphore_(0), 1795 : in_semaphore_(0),
1782 out_semaphore_(0), 1796 out_semaphore_(0),
1783 thread_(NULL), 1797 thread_(NULL),
1784 script_(NULL), 1798 script_(NULL),
1785 state_(IDLE), 1799 state_(IDLE) {}
1786 join_called_(false) {}
1787 1800
1788 1801
1789 Worker::~Worker() { 1802 Worker::~Worker() {
1790 delete thread_; 1803 delete thread_;
1791 thread_ = NULL; 1804 thread_ = NULL;
1792 delete[] script_; 1805 delete[] script_;
1793 script_ = NULL; 1806 script_ = NULL;
1794 in_queue_.Clear(); 1807 in_queue_.Clear();
1795 out_queue_.Clear(); 1808 out_queue_.Clear();
1796 } 1809 }
1797 1810
1798 1811
1799 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) { 1812 void Worker::StartExecuteInThread(Isolate* isolate, const char* script) {
1800 if (base::NoBarrier_CompareAndSwap(&state_, IDLE, RUNNING) == IDLE) { 1813 DCHECK(state_ == IDLE);
1801 script_ = i::StrDup(script); 1814 state_ = RUNNING;
1802 thread_ = new WorkerThread(this); 1815
1803 thread_->Start(); 1816 script_ = i::StrDup(script);
1804 } else { 1817 thread_ = new WorkerThread(this);
1805 // Somehow the Worker was started twice. 1818 thread_->Start();
1806 UNREACHABLE();
1807 }
1808 } 1819 }
1809 1820
1810 1821
1811 void Worker::PostMessage(SerializationData* data) { 1822 void Worker::PostMessage(SerializationData* data) {
1812 in_queue_.Enqueue(data); 1823 in_queue_.Enqueue(data);
1813 in_semaphore_.Signal(); 1824 in_semaphore_.Signal();
1814 } 1825 }
1815 1826
1816 1827
1817 SerializationData* Worker::GetMessage() { 1828 SerializationData* Worker::GetMessage() {
1818 SerializationData* data = NULL; 1829 SerializationData* data = NULL;
1819 while (!out_queue_.Dequeue(&data)) { 1830 while (!out_queue_.Dequeue(&data)) {
1820 // If the worker is no longer running, and there are no messages in the 1831 // If the worker is no longer running, and there are no messages in the
1821 // queue, don't expect any more messages from it. 1832 // queue, don't expect any more messages from it.
1822 if (base::NoBarrier_Load(&state_) != RUNNING) break; 1833 if (state_ != RUNNING) break;
1823 out_semaphore_.Wait(); 1834 out_semaphore_.Wait();
1824 } 1835 }
1825 return data; 1836 return data;
1826 } 1837 }
1827 1838
1828 1839
1829 void Worker::Terminate() { 1840 void Worker::Terminate() {
1830 if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { 1841 if (state_ == RUNNING) {
1842 state_ = TERMINATED;
Jarin 2015/07/23 07:48:41 What if we call quit() from one worker and worker.
binji 2015/07/24 18:52:29 Yes, you're right. I've removed the state_ (becaus
1831 // Post NULL to wake the Worker thread message loop, and tell it to stop 1843 // Post NULL to wake the Worker thread message loop, and tell it to stop
1832 // running. 1844 // running.
1833 PostMessage(NULL); 1845 PostMessage(NULL);
1834 } 1846 }
1835 } 1847 }
1836 1848
1837 1849
1838 void Worker::WaitForThread() { 1850 void Worker::WaitForThread() {
1839 Terminate(); 1851 Terminate();
1840 1852 thread_->Join();
1841 if (base::NoBarrier_CompareAndSwap(&join_called_, false, true) == false) {
1842 thread_->Join();
1843 } else {
1844 // Tried to call join twice.
1845 UNREACHABLE();
1846 }
1847 } 1853 }
1848 1854
1849 1855
1850 void Worker::ExecuteInThread() { 1856 void Worker::ExecuteInThread() {
1851 Isolate::CreateParams create_params; 1857 Isolate::CreateParams create_params;
1852 create_params.array_buffer_allocator = Shell::array_buffer_allocator; 1858 create_params.array_buffer_allocator = Shell::array_buffer_allocator;
1853 Isolate* isolate = Isolate::New(create_params); 1859 Isolate* isolate = Isolate::New(create_params);
1854 { 1860 {
1855 Isolate::Scope iscope(isolate); 1861 Isolate::Scope iscope(isolate);
1856 { 1862 {
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 } 2612 }
2607 2613
2608 } // namespace v8 2614 } // namespace v8
2609 2615
2610 2616
2611 #ifndef GOOGLE3 2617 #ifndef GOOGLE3
2612 int main(int argc, char* argv[]) { 2618 int main(int argc, char* argv[]) {
2613 return v8::Shell::Main(argc, argv); 2619 return v8::Shell::Main(argc, argv);
2614 } 2620 }
2615 #endif 2621 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/regress/regress-crbug-511880.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698