Reviewed by Darin.
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Aug 2006 23:15:27 +0000 (23:15 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Aug 2006 23:15:27 +0000 (23:15 +0000)
        Bug 10200: [Drosera] Deadlock between Drosera and Safari while loading page
        http://bugzilla.opendarwin.org/show_bug.cgi?id=10200

        Prevent reentrancy in our debugger callbacks. This was causing a deadlock in Drosera because
        suspendProcessIfPaused was being called during a DO call into Safari.

        Preventing reentrancy also prevents scripts that Drosera injects and evaluates from showing
        up in rare cases (such as a iframe loading about:blank). I thought this would prevent cases
        where you call a function from the console and expect it to break on a breakpoint in them, but
        this appears to never have worked even without this change. When that is figured out we can
        reconsider a better solution to reentrancy. I have filed that as bug 10214.

        I also removed the NSRunLoop runMode:beforeDate: calls since DO handles this for us since
        we don't use "onway void" as the return type for the callbacks. Note: using onway void for
        the listener callbacks causes bad synchronization issues and obscure crashes.

        * DefaultDelegates/WebScriptDebugServer.m:
        (-[WebScriptDebugServer webView:didLoadMainResourceForDataSource:]):
        (-[WebScriptDebugServer webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:]):
        (-[WebScriptDebugServer webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:]):
        (-[WebScriptDebugServer webView:didEnterCallFrame:sourceId:line:forWebFrame:]):
        (-[WebScriptDebugServer webView:willExecuteStatement:sourceId:line:forWebFrame:]):
        (-[WebScriptDebugServer webView:willLeaveCallFrame:sourceId:line:forWebFrame:]):
        (-[WebScriptDebugServer webView:exceptionWasRaised:sourceId:line:forWebFrame:]):
        * DefaultDelegates/WebScriptDebugServerPrivate.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15761 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/DefaultDelegates/WebScriptDebugServer.m
WebKit/DefaultDelegates/WebScriptDebugServerPrivate.h

index 8a30cd497d9ad349d107597d3d36b81df793e0e3..3b796e87a49503e6391b1f000ba8a620b35c4501 100644 (file)
@@ -1,3 +1,33 @@
+2006-08-02  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin.
+
+        Bug 10200: [Drosera] Deadlock between Drosera and Safari while loading page
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=10200
+
+        Prevent reentrancy in our debugger callbacks. This was causing a deadlock in Drosera because
+        suspendProcessIfPaused was being called during a DO call into Safari.
+
+        Preventing reentrancy also prevents scripts that Drosera injects and evaluates from showing
+        up in rare cases (such as a iframe loading about:blank). I thought this would prevent cases
+        where you call a function from the console and expect it to break on a breakpoint in them, but
+        this appears to never have worked even without this change. When that is figured out we can
+        reconsider a better solution to reentrancy. I have filed that as bug 10214.
+
+        I also removed the NSRunLoop runMode:beforeDate: calls since DO handles this for us since
+        we don't use "onway void" as the return type for the callbacks. Note: using onway void for
+        the listener callbacks causes bad synchronization issues and obscure crashes.
+
+        * DefaultDelegates/WebScriptDebugServer.m:
+        (-[WebScriptDebugServer webView:didLoadMainResourceForDataSource:]):
+        (-[WebScriptDebugServer webView:didParseSource:baseLineNumber:fromURL:sourceId:forWebFrame:]):
+        (-[WebScriptDebugServer webView:failedToParseSource:baseLineNumber:fromURL:withError:forWebFrame:]):
+        (-[WebScriptDebugServer webView:didEnterCallFrame:sourceId:line:forWebFrame:]):
+        (-[WebScriptDebugServer webView:willExecuteStatement:sourceId:line:forWebFrame:]):
+        (-[WebScriptDebugServer webView:willLeaveCallFrame:sourceId:line:forWebFrame:]):
+        (-[WebScriptDebugServer webView:exceptionWasRaised:sourceId:line:forWebFrame:]):
+        * DefaultDelegates/WebScriptDebugServerPrivate.h:
+
 2006-08-02  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by John.
index 3ab476b298a2b23abe05ce871daa2e68389f1f8f..fde08ebc98e6fbd00ee5d31467ba82177c4d84d3 100644 (file)
@@ -215,9 +215,11 @@ static unsigned listenerCount = 0;
 
 - (void)webView:(WebView *)webView didLoadMainResourceForDataSource:(WebDataSource *)dataSource
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -225,6 +227,8 @@ static unsigned listenerCount = 0;
         if ([[listener connectionForProxy] isValid])
             [listener webView:webView didLoadMainResourceForDataSource:dataSource];
     }
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView       didParseSource:(NSString *)source
@@ -233,9 +237,11 @@ static unsigned listenerCount = 0;
                                                sourceId:(int)sid
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -243,6 +249,8 @@ static unsigned listenerCount = 0;
         if ([[listener connectionForProxy] isValid])
             [listener webView:webView didParseSource:source baseLineNumber:lineNumber fromURL:url sourceId:sid forWebFrame:webFrame];
     }
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView  failedToParseSource:(NSString *)source
@@ -251,9 +259,11 @@ static unsigned listenerCount = 0;
                                               withError:(NSError *)error
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -261,6 +271,8 @@ static unsigned listenerCount = 0;
         if ([[listener connectionForProxy] isValid])
             [listener webView:webView failedToParseSource:source baseLineNumber:lineNumber fromURL:url withError:error forWebFrame:webFrame];
     }
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView    didEnterCallFrame:(WebScriptCallFrame *)frame
@@ -268,9 +280,11 @@ static unsigned listenerCount = 0;
                                                    line:(int)lineno
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -279,10 +293,9 @@ static unsigned listenerCount = 0;
             [listener webView:webView didEnterCallFrame:frame sourceId:sid line:lineno forWebFrame:webFrame];
     }
 
-    // check for messages from the listeners, so they can pause immediately
-    [[NSRunLoop currentRunLoop] runMode:NSConnectionReplyMode beforeDate:[NSDate distantPast]];
-
     [self suspendProcessIfPaused];
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView willExecuteStatement:(WebScriptCallFrame *)frame
@@ -290,9 +303,11 @@ static unsigned listenerCount = 0;
                                                    line:(int)lineno
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -301,10 +316,9 @@ static unsigned listenerCount = 0;
             [listener webView:webView willExecuteStatement:frame sourceId:sid line:lineno forWebFrame:webFrame];
     }
 
-    // check for messages from the listeners, so they can pause immediately
-    [[NSRunLoop currentRunLoop] runMode:NSConnectionReplyMode beforeDate:[NSDate distantPast]];
-
     [self suspendProcessIfPaused];
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView   willLeaveCallFrame:(WebScriptCallFrame *)frame
@@ -312,9 +326,11 @@ static unsigned listenerCount = 0;
                                                    line:(int)lineno
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -323,10 +339,9 @@ static unsigned listenerCount = 0;
             [listener webView:webView willLeaveCallFrame:frame sourceId:sid line:lineno forWebFrame:webFrame];
     }
 
-    // check for messages from the listeners, so they can pause immediately
-    [[NSRunLoop currentRunLoop] runMode:NSConnectionReplyMode beforeDate:[NSDate distantPast]];
-
     [self suspendProcessIfPaused];
+
+    inCallback = NO;
 }
 
 - (void)webView:(WebView *)webView   exceptionWasRaised:(WebScriptCallFrame *)frame
@@ -334,9 +349,11 @@ static unsigned listenerCount = 0;
                                                    line:(int)lineno
                                             forWebFrame:(WebFrame *)webFrame
 {
-    if (![listeners count])
+    if (![listeners count] || inCallback)
         return;
 
+    inCallback = YES;
+
     NSEnumerator *enumerator = [listeners objectEnumerator];
     NSDistantObject <WebScriptDebugListener> *listener = nil;
 
@@ -345,10 +362,9 @@ static unsigned listenerCount = 0;
             [listener webView:webView exceptionWasRaised:frame sourceId:sid line:lineno forWebFrame:webFrame];
     }
 
-    // check for messages from the listeners, so they can pause immediately
-    [[NSRunLoop currentRunLoop] runMode:NSConnectionReplyMode beforeDate:[NSDate distantPast]];
-
     [self suspendProcessIfPaused];
+
+    inCallback = NO;
 }
 
 @end
index 25f0ef5dad41a2ef9b0bca1bea45fd56631a21d1..b05632f0aca2cb16c5b7c0272ff180436425a639 100644 (file)
@@ -33,6 +33,7 @@
     NSConnection *serverConnection;
     NSString *serverName;
     NSMutableSet *listeners;
+    BOOL inCallback;
     BOOL paused;
     BOOL step;
 }