Reviewed by Darin Adler.

        https://bugs.webkit.org/show_bug.cgi?id=22397
        Worker threads are not destroyed if running a JS loop

        Since the event loop is not ever entered again in this case, the fix necessarily involves
        some shared data hackery.

        * dom/WorkerThread.cpp: (WebCore::WorkerThread::stop):
        * dom/WorkerThread.h:
        Added a stop() method, which asks the thread to exit as soon as possible. In the future, it
        may need to abort other kinds of synchronous processing, such as importScripts or XHR.

        * bindings/js/WorkerScriptController.cpp:
        (WebCore::WorkerScriptController::WorkerScriptController):
        (WebCore::WorkerScriptController::evaluate):
        (WebCore::WorkerScriptController::forbidExecution):
        * bindings/js/WorkerScriptController.h:
        Added a forbidExecution() method, which interrupts currently running JS, and makes any
        future calls to evaluate() return immediately.

        * dom/WorkerMessagingProxy.cpp: (WebCore::WorkerMessagingProxy::workerObjectDestroyed):
        Call WorkerThread::stop().



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38689 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp
index a08dbc0..bbda011 100644
--- a/WebCore/bindings/js/WorkerScriptController.cpp
+++ b/WebCore/bindings/js/WorkerScriptController.cpp
@@ -35,6 +35,7 @@
 #include "WorkerContext.h"
 #include "WorkerMessagingProxy.h"
 #include "WorkerThread.h"
+#include <interpreter/Interpreter.h>
 #include <parser/SourceCode.h>
 #include <runtime/Completion.h>
 #include <runtime/Completion.h>
@@ -47,6 +48,7 @@
 WorkerScriptController::WorkerScriptController(WorkerContext* workerContext)
     : m_globalData(JSGlobalData::create())
     , m_workerContext(workerContext)
+    , m_executionForbidded(false)
 {
 }
 
@@ -70,6 +72,12 @@
 
 JSValue* WorkerScriptController::evaluate(const JSC::SourceCode& sourceCode)
 {
+    {
+        MutexLocker lock(m_sharedDataMutex);
+        if (m_executionForbidded)
+            return noValue();
+    }
+
     initScriptIfNeeded();
     JSLock lock(false);
 
@@ -88,6 +96,17 @@
     return noValue();
 }
 
+void WorkerScriptController::forbidExecution()
+{
+    // This function is called from another thread.
+    // Mutex protection for m_executionForbidded is needed to guarantee that the value is synchronized between processors, because
+    // if it were not, the worker could re-enter JSC::evaluate(), but with timeout already reset.
+    // It is not critical for Interpreter::m_timeoutTime to be synchronized, we just rely on it reaching the worker thread's processor sooner or later.
+    MutexLocker lock(m_sharedDataMutex);
+    m_executionForbidded = true;
+    m_globalData->interpreter->setTimeoutTime(1); // 1 ms is the smallest timeout that can be set.
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WORKERS)