Title: [108344] trunk/Source
Revision
108344
Author
[email protected]
Date
2012-02-21 05:10:35 -0800 (Tue, 21 Feb 2012)

Log Message

[V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop
https://bugs.webkit.org/show_bug.cgi?id=79097

Source/WebCore:

Worker script will be interrupted to dispatch all arriving inspector commands.
This way debugger will be operable even if worker is in a tight loop.

Reviewed by Pavel Feldman.

* bindings/js/ScriptDebugServer.h:
(Task):
(WebCore::ScriptDebugServer::Task::~Task):
(ScriptDebugServer):
* bindings/js/WorkerScriptDebugServer.cpp:
(WebCore::WorkerScriptDebugServer::interruptAndRunTask):
(WebCore):
* bindings/js/WorkerScriptDebugServer.h:
(WorkerScriptDebugServer):
* bindings/v8/ScriptDebugServer.cpp:
(WebCore::ScriptDebugServer::interruptAndRun):
* bindings/v8/ScriptDebugServer.h:
(ScriptDebugServer):
* bindings/v8/WorkerScriptDebugServer.cpp:
(WebCore::WorkerScriptDebugServer::WorkerScriptDebugServer):
(WebCore::WorkerScriptDebugServer::interruptAndRunTask):
(WebCore):
* bindings/v8/WorkerScriptDebugServer.h:
(v8):
(WebCore):
(WorkerScriptDebugServer):
* inspector/WorkerDebuggerAgent.cpp:
(WebCore::WorkerDebuggerAgent::WorkerDebuggerAgent):
(WebCore::WorkerDebuggerAgent::~WorkerDebuggerAgent):
(WebCore):
(WebCore::WorkerDebuggerAgent::interruptAndDispatchInspectorCommands):
* inspector/WorkerDebuggerAgent.h:
(WebCore):
(WorkerDebuggerAgent):
* workers/WorkerMessagingProxy.cpp:
(WebCore):
(WebCore::WorkerMessagingProxy::sendMessageToInspector):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::run):
(WebCore::WorkerRunLoop::runInMode):
* workers/WorkerRunLoop.h:
(WorkerRunLoop):

Source/WebKit/chromium:

Worker script execution will be interrupted for dispatching inspector commands.

Reviewed by Pavel Feldman.

* src/WebSharedWorkerImpl.cpp:
(WebKit::WebSharedWorkerImpl::dispatchDevToolsMessage):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (108343 => 108344)


--- trunk/Source/WebCore/ChangeLog	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/ChangeLog	2012-02-21 13:10:35 UTC (rev 108344)
@@ -1,3 +1,51 @@
+2012-02-21  Yury Semikhatsky  <[email protected]>
+
+        [V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop
+        https://bugs.webkit.org/show_bug.cgi?id=79097
+
+        Worker script will be interrupted to dispatch all arriving inspector commands.
+        This way debugger will be operable even if worker is in a tight loop.
+
+        Reviewed by Pavel Feldman.
+
+        * bindings/js/ScriptDebugServer.h:
+        (Task):
+        (WebCore::ScriptDebugServer::Task::~Task):
+        (ScriptDebugServer):
+        * bindings/js/WorkerScriptDebugServer.cpp:
+        (WebCore::WorkerScriptDebugServer::interruptAndRunTask):
+        (WebCore):
+        * bindings/js/WorkerScriptDebugServer.h:
+        (WorkerScriptDebugServer):
+        * bindings/v8/ScriptDebugServer.cpp:
+        (WebCore::ScriptDebugServer::interruptAndRun):
+        * bindings/v8/ScriptDebugServer.h:
+        (ScriptDebugServer):
+        * bindings/v8/WorkerScriptDebugServer.cpp:
+        (WebCore::WorkerScriptDebugServer::WorkerScriptDebugServer):
+        (WebCore::WorkerScriptDebugServer::interruptAndRunTask):
+        (WebCore):
+        * bindings/v8/WorkerScriptDebugServer.h:
+        (v8):
+        (WebCore):
+        (WorkerScriptDebugServer):
+        * inspector/WorkerDebuggerAgent.cpp:
+        (WebCore::WorkerDebuggerAgent::WorkerDebuggerAgent):
+        (WebCore::WorkerDebuggerAgent::~WorkerDebuggerAgent):
+        (WebCore):
+        (WebCore::WorkerDebuggerAgent::interruptAndDispatchInspectorCommands):
+        * inspector/WorkerDebuggerAgent.h:
+        (WebCore):
+        (WorkerDebuggerAgent):
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore):
+        (WebCore::WorkerMessagingProxy::sendMessageToInspector):
+        * workers/WorkerRunLoop.cpp:
+        (WebCore::WorkerRunLoop::run):
+        (WebCore::WorkerRunLoop::runInMode):
+        * workers/WorkerRunLoop.h:
+        (WorkerRunLoop):
+
 2012-02-21  'Pavel Feldman'  <[email protected]>
 
         Not reviewed: fixing Mac build (take 2).

Modified: trunk/Source/WebCore/bindings/js/ScriptDebugServer.h (108343 => 108344)


--- trunk/Source/WebCore/bindings/js/ScriptDebugServer.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/ScriptDebugServer.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -92,6 +92,12 @@
 
     bool isPaused() { return m_paused; }
 
+    class Task {
+    public:
+        virtual ~Task() { }
+        virtual void run() = 0;
+    };
+
 protected:
     typedef HashSet<ScriptDebugListener*> ListenerSet;
     typedef void (ScriptDebugServer::*_javascript_ExecutionCallback)(ScriptDebugListener*);

Modified: trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp (108343 => 108344)


--- trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -33,6 +33,7 @@
 #if ENABLE(_javascript__DEBUGGER) && ENABLE(WORKERS)
 
 #include "WorkerScriptDebugServer.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
 
@@ -51,6 +52,10 @@
 {
 }
 
+void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>)
+{
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(_javascript__DEBUGGER) && ENABLE(WORKERS)

Modified: trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h (108343 => 108344)


--- trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -50,6 +50,8 @@
 
     static const char* debuggerTaskMode;
 
+    void interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>);
+
 private:
     virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>*) { }
     virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) { return 0; }

Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp (108343 => 108344)


--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -268,9 +268,9 @@
     return ScriptValue(toV8(currentCallFrame.release()));
 }
 
-void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task)
+void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task, v8::Isolate* isolate)
 {
-    v8::Debug::DebugBreakForCommand(new ClientDataImpl(task));
+    v8::Debug::DebugBreakForCommand(new ClientDataImpl(task), isolate);
 }
 
 void ScriptDebugServer::runPendingTasks()

Modified: trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h (108343 => 108344)


--- trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -89,7 +89,7 @@
         virtual ~Task() { }
         virtual void run() = 0;
     };
-    static void interruptAndRun(PassOwnPtr<Task>);
+    static void interruptAndRun(PassOwnPtr<Task>, v8::Isolate* = 0);
     void runPendingTasks();
 
     bool isPaused();

Modified: trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp (108343 => 108344)


--- trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -41,13 +41,16 @@
 #include <v8.h>
 #include <wtf/MessageQueue.h>
 
+
 namespace WebCore {
 
 WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerContext* workerContext)
     : ScriptDebugServer()
     , m_listener(0)
     , m_workerContext(workerContext)
+    , m_isolate(v8::Isolate::GetCurrent())
 {
+    ASSERT(m_isolate);
 }
 
 void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener)
@@ -87,6 +90,11 @@
     v8::Debug::SetDebugEventListener2(0);
 }
 
+void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<Task> task)
+{
+    interruptAndRun(task, m_isolate);
+}
+
 ScriptDebugListener* WorkerScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context>)
 {
     // There is only one worker context in isolate.

Modified: trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h (108343 => 108344)


--- trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -35,9 +35,14 @@
 
 #include "ScriptDebugServer.h"
 
+namespace v8 {
+class Isolate;
+}
+
 namespace WebCore {
 
 class WorkerContext;
+class WorkerThread;
 
 class WorkerScriptDebugServer : public ScriptDebugServer {
     WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer);
@@ -48,6 +53,8 @@
     void addListener(ScriptDebugListener*);
     void removeListener(ScriptDebugListener*);
 
+    void interruptAndRunTask(PassOwnPtr<Task>);
+
 private:
     virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>);
     virtual void runMessageLoopOnPause(v8::Handle<v8::Context>);
@@ -56,6 +63,7 @@
     typedef HashMap<WorkerContext*, ScriptDebugListener*> ListenersMap;
     ScriptDebugListener* m_listener;
     WorkerContext* m_workerContext;
+    v8::Isolate* m_isolate;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp (108343 => 108344)


--- trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/inspector/WorkerDebuggerAgent.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -34,9 +34,49 @@
 #if ENABLE(_javascript__DEBUGGER) && ENABLE(INSPECTOR) && ENABLE(WORKERS)
 #include "ScriptDebugServer.h"
 #include "WorkerContext.h"
+#include "WorkerThread.h"
+#include <wtf/MessageQueue.h>
 
 namespace WebCore {
 
+namespace {
+
+Mutex& workerDebuggerAgentsMutex()
+{
+    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+    return mutex;
+}
+
+typedef HashMap<WorkerThread*, WorkerDebuggerAgent*> WorkerDebuggerAgents;
+
+WorkerDebuggerAgents& workerDebuggerAgents()
+{
+    DEFINE_STATIC_LOCAL(WorkerDebuggerAgents, agents, ());
+    return agents;
+}
+
+
+class RunInspectorCommandsTask : public ScriptDebugServer::Task {
+public:
+    RunInspectorCommandsTask(WorkerThread* thread, WorkerContext* workerContext)
+        : m_thread(thread)
+        , m_workerContext(workerContext) { }
+    virtual ~RunInspectorCommandsTask() { }
+    virtual void run()
+    {
+        // Process all queued debugger commands. It is safe to use m_workerContext here
+        // because it is alive if RunWorkerLoop is not terminated, otherwise it will
+        // just be ignored.
+        while (MessageQueueMessageReceived == m_thread->runLoop().runInMode(m_workerContext, WorkerDebuggerAgent::debuggerTaskMode, WorkerRunLoop::DontWaitForMessage)) { }
+    }
+
+private:
+    RefPtr<WorkerThread> m_thread;
+    WorkerContext* m_workerContext;
+};
+
+} // namespace
+
 const char* WorkerDebuggerAgent::debuggerTaskMode = "debugger";
 
 PassOwnPtr<WorkerDebuggerAgent> WorkerDebuggerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorState* inspectorState, WorkerContext* inspectedWorkerContext, InjectedScriptManager* injectedScriptManager)
@@ -49,12 +89,25 @@
     , m_scriptDebugServer(inspectedWorkerContext)
     , m_inspectedWorkerContext(inspectedWorkerContext)
 {
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    workerDebuggerAgents().set(inspectedWorkerContext->thread(), this);
 }
 
 WorkerDebuggerAgent::~WorkerDebuggerAgent()
 {
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    ASSERT(workerDebuggerAgents().contains(m_inspectedWorkerContext->thread()));
+    workerDebuggerAgents().remove(m_inspectedWorkerContext->thread());
 }
 
+void WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(WorkerThread* thread)
+{
+    MutexLocker lock(workerDebuggerAgentsMutex());
+    WorkerDebuggerAgent* agent = workerDebuggerAgents().get(thread);
+    if (agent)
+        agent->m_scriptDebugServer.interruptAndRunTask(adoptPtr(new RunInspectorCommandsTask(thread, agent->m_inspectedWorkerContext)));
+}
+
 void WorkerDebuggerAgent::startListeningScriptDebugServer()
 {
     scriptDebugServer().addListener(this);

Modified: trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h (108343 => 108344)


--- trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/inspector/WorkerDebuggerAgent.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -38,6 +38,7 @@
 namespace WebCore {
 
 class WorkerContext;
+class WorkerThread;
 
 class WorkerDebuggerAgent : public InspectorDebuggerAgent {
     WTF_MAKE_NONCOPYABLE(WorkerDebuggerAgent);
@@ -47,6 +48,7 @@
     virtual ~WorkerDebuggerAgent();
 
     static const char* debuggerTaskMode;
+    static void interruptAndDispatchInspectorCommands(WorkerThread*);
 
 private:
     WorkerDebuggerAgent(InstrumentingAgents*, InspectorState*, WorkerContext*, InjectedScriptManager*);

Modified: trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp (108343 => 108344)


--- trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -21,7 +21,7 @@
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
 
@@ -316,7 +316,7 @@
 {
     m_scriptExecutionContext->postTask(WorkerExceptionTask::create(errorMessage, lineNumber, sourceURL, this));
 }
-    
+
 static void postConsoleMessageTask(ScriptExecutionContext* context, WorkerMessagingProxy* messagingProxy, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL)
 {
     if (messagingProxy->askedToTerminate())
@@ -411,6 +411,7 @@
         return;
 #if ENABLE(_javascript__DEBUGGER)
     m_workerThread->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode);
+    WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(m_workerThread.get());
 #endif
 }
 #endif

Modified: trunk/Source/WebCore/workers/WorkerRunLoop.cpp (108343 => 108344)


--- trunk/Source/WebCore/workers/WorkerRunLoop.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -132,26 +132,28 @@
     ModePredicate modePredicate(defaultMode());
     MessageQueueWaitResult result;
     do {
-        result = runInMode(context, modePredicate);
+        result = runInMode(context, modePredicate, WaitForMessage);
     } while (result != MessageQueueTerminated);
     runCleanupTasks(context);
 }
 
-MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const String& mode)
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const String& mode, WaitMode waitMode)
 {
     RunLoopSetup setup(*this);
     ModePredicate modePredicate(mode);
-    MessageQueueWaitResult result = runInMode(context, modePredicate);
+    MessageQueueWaitResult result = runInMode(context, modePredicate, waitMode);
     return result;
 }
 
-MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate)
+MessageQueueWaitResult WorkerRunLoop::runInMode(WorkerContext* context, const ModePredicate& predicate, WaitMode waitMode)
 {
     ASSERT(context);
     ASSERT(context->thread());
     ASSERT(context->thread()->threadID() == currentThread());
 
-    double absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime();
+    double absoluteTime = 0.0;
+    if (waitMode == WaitForMessage)
+        absoluteTime = (predicate.isDefaultMode() && m_sharedTimer->isActive()) ? m_sharedTimer->fireTime() : MessageQueue<Task>::infiniteTime();
     MessageQueueWaitResult result;
     OwnPtr<WorkerRunLoop::Task> task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime);
 

Modified: trunk/Source/WebCore/workers/WorkerRunLoop.h (108343 => 108344)


--- trunk/Source/WebCore/workers/WorkerRunLoop.h	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.h	2012-02-21 13:10:35 UTC (rev 108344)
@@ -52,8 +52,10 @@
         // Blocking call. Waits for tasks and timers, invokes the callbacks.
         void run(WorkerContext*);
 
+        enum WaitMode { WaitForMessage, DontWaitForMessage };
+
         // Waits for a single task and returns.
-        MessageQueueWaitResult runInMode(WorkerContext*, const String& mode);
+        MessageQueueWaitResult runInMode(WorkerContext*, const String& mode, WaitMode = WaitForMessage);
 
         void terminate();
         bool terminated() const { return m_messageQueue.killed(); }
@@ -82,7 +84,7 @@
 
     private:
         friend class RunLoopSetup;
-        MessageQueueWaitResult runInMode(WorkerContext*, const ModePredicate&);
+        MessageQueueWaitResult runInMode(WorkerContext*, const ModePredicate&, WaitMode);
 
         // Runs any clean up tasks that are currently in the queue and returns.
         // This should only be called when the context is closed or loop has been terminated.

Modified: trunk/Source/WebKit/chromium/ChangeLog (108343 => 108344)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-02-21 13:10:35 UTC (rev 108344)
@@ -1,3 +1,15 @@
+2012-02-21  Yury Semikhatsky  <[email protected]>
+
+        [V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop
+        https://bugs.webkit.org/show_bug.cgi?id=79097
+
+        Worker script execution will be interrupted for dispatching inspector commands.
+
+        Reviewed by Pavel Feldman.
+
+        * src/WebSharedWorkerImpl.cpp:
+        (WebKit::WebSharedWorkerImpl::dispatchDevToolsMessage):
+
 2012-02-20  Peter Beverloo  <[email protected]>
 
         Unreviewed.  Rolled DEPS.

Modified: trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp (108343 => 108344)


--- trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp	2012-02-21 13:05:04 UTC (rev 108343)
+++ trunk/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp	2012-02-21 13:10:35 UTC (rev 108344)
@@ -443,6 +443,7 @@
 void WebSharedWorkerImpl::dispatchDevToolsMessage(const WebString& message)
 {
     workerThread()->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode);
+    WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(workerThread());
 }
 
 WebSharedWorker* WebSharedWorker::create(WebSharedWorkerClient* client)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to