<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[213228] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/213228">213228</a></dd>
<dt>Author</dt> <dd>bburg@apple.com</dd>
<dt>Date</dt> <dd>2017-03-01 10:03:53 -0800 (Wed, 01 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/211344">r211344</a>): Remote Inspector: listingForAutomationTarget() is called off-main-thread, causing assertions
https://bugs.webkit.org/show_bug.cgi?id=168695
&lt;rdar://problem/30643899&gt;

Reviewed by Joseph Pecoraro.

The aforementioned commit added some new calls to update target listings. This causes RemoteInspector
to update some listings underneath an incoming setup message on the XPC queue, which is not a safe place
to gather listing information for RemoteAutomationTargets.

Update the listing asynchronously since we don't need it immediately. Since this really only happens when
the connection to the target is set up and shut down, we can trigger listings to be refreshed from
the async block that's called on the target's queue inside RemoteConnectionToTarget::{setup,close}.

* inspector/remote/RemoteInspector.h:
Make updateListingForTarget(unsigned) usable from RemoteConnectionToTarget.

* inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm:
(Inspector::RemoteConnectionToTarget::setup):
(Inspector::RemoteConnectionToTarget::close):
Grab the target identifier while the RemoteControllableTarget pointer is still valid,
and use it inside the block later after it may have been destructed already. If that happens,
then updateTargetListing will bail out because the targetIdentifier cannot be found in the mapping.

* inspector/remote/cocoa/RemoteInspectorCocoa.mm:
(Inspector::RemoteInspector::updateTargetListing):
We need to make sure to request a listing push after the target is updated, so implicitly call
pushListingsSoon() from here. That method doesn't require any particular queue or holding a lock.

(Inspector::RemoteInspector::receivedSetupMessage):
(Inspector::RemoteInspector::receivedDidCloseMessage):
(Inspector::RemoteInspector::receivedConnectionDiedMessage):
Remove calls to updateTargetListing() and pushListingsSoon(), as these happen implicitly
and asynchronously on the target's queue when the connection to target is opened or closed.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorremoteRemoteInspectorh">trunk/Source/JavaScriptCore/inspector/remote/RemoteInspector.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorremotecocoaRemoteConnectionToTargetCocoamm">trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorremotecocoaRemoteInspectorCocoamm">trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteInspectorCocoa.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213227 => 213228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-01 17:49:59 UTC (rev 213227)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-01 18:03:53 UTC (rev 213228)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2017-02-28  Brian Burg  &lt;bburg@apple.com&gt;
+
+        REGRESSION(r211344): Remote Inspector: listingForAutomationTarget() is called off-main-thread, causing assertions
+        https://bugs.webkit.org/show_bug.cgi?id=168695
+        &lt;rdar://problem/30643899&gt;
+
+        Reviewed by Joseph Pecoraro.
+
+        The aforementioned commit added some new calls to update target listings. This causes RemoteInspector
+        to update some listings underneath an incoming setup message on the XPC queue, which is not a safe place
+        to gather listing information for RemoteAutomationTargets.
+
+        Update the listing asynchronously since we don't need it immediately. Since this really only happens when
+        the connection to the target is set up and shut down, we can trigger listings to be refreshed from
+        the async block that's called on the target's queue inside RemoteConnectionToTarget::{setup,close}.
+
+        * inspector/remote/RemoteInspector.h:
+        Make updateListingForTarget(unsigned) usable from RemoteConnectionToTarget.
+
+        * inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm:
+        (Inspector::RemoteConnectionToTarget::setup):
+        (Inspector::RemoteConnectionToTarget::close):
+        Grab the target identifier while the RemoteControllableTarget pointer is still valid,
+        and use it inside the block later after it may have been destructed already. If that happens,
+        then updateTargetListing will bail out because the targetIdentifier cannot be found in the mapping.
+
+        * inspector/remote/cocoa/RemoteInspectorCocoa.mm:
+        (Inspector::RemoteInspector::updateTargetListing):
+        We need to make sure to request a listing push after the target is updated, so implicitly call
+        pushListingsSoon() from here. That method doesn't require any particular queue or holding a lock.
+
+        (Inspector::RemoteInspector::receivedSetupMessage):
+        (Inspector::RemoteInspector::receivedDidCloseMessage):
+        (Inspector::RemoteInspector::receivedConnectionDiedMessage):
+        Remove calls to updateTargetListing() and pushListingsSoon(), as these happen implicitly
+        and asynchronously on the target's queue when the connection to target is opened or closed.
+
</ins><span class="cx"> 2017-03-01  Tomas Popela  &lt;tpopela@redhat.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Leak under Options::setOptions
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorremoteRemoteInspectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/remote/RemoteInspector.h (213227 => 213228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/remote/RemoteInspector.h        2017-03-01 17:49:59 UTC (rev 213227)
+++ trunk/Source/JavaScriptCore/inspector/remote/RemoteInspector.h        2017-03-01 18:03:53 UTC (rev 213228)
</span><span class="lines">@@ -94,6 +94,8 @@
</span><span class="cx">     RetainPtr&lt;CFDataRef&gt; parentProcessAuditData() const { return m_parentProcessAuditData; }
</span><span class="cx">     void setParentProcessInformation(pid_t, RetainPtr&lt;CFDataRef&gt; auditData);
</span><span class="cx">     void setParentProcessInfomationIsDelayed();
</span><ins>+
+    void updateTargetListing(unsigned targetIdentifier);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -115,7 +117,6 @@
</span><span class="cx">     void pushListingsNow();
</span><span class="cx">     void pushListingsSoon();
</span><span class="cx"> 
</span><del>-    void updateTargetListing(unsigned targetIdentifier);
</del><span class="cx">     void updateTargetListing(const RemoteControllableTarget&amp;);
</span><span class="cx"> 
</span><span class="cx">     void updateHasActiveDebugSession();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorremotecocoaRemoteConnectionToTargetCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm (213227 => 213228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm        2017-03-01 17:49:59 UTC (rev 213227)
+++ trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm        2017-03-01 18:03:53 UTC (rev 213228)
</span><span class="lines">@@ -159,12 +159,15 @@
</span><span class="cx">     if (!m_target)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    unsigned targetIdentifier = this-&gt;targetIdentifier().value_or(0);
+    
</ins><span class="cx">     ref();
</span><span class="cx">     dispatchAsyncOnTarget(^{
</span><span class="cx">         {
</span><span class="cx">             std::lock_guard&lt;Lock&gt; lock(m_targetMutex);
</span><ins>+
</ins><span class="cx">             if (!m_target || !m_target-&gt;remoteControlAllowed()) {
</span><del>-                RemoteInspector::singleton().setupFailed(targetIdentifier().value_or(0));
</del><ins>+                RemoteInspector::singleton().setupFailed(targetIdentifier);
</ins><span class="cx">                 m_target = nullptr;
</span><span class="cx">             } else if (is&lt;RemoteInspectionTarget&gt;(m_target)) {
</span><span class="cx">                 auto castedTarget = downcast&lt;RemoteInspectionTarget&gt;(m_target);
</span><span class="lines">@@ -173,10 +176,14 @@
</span><span class="cx"> 
</span><span class="cx">                 if (automaticallyPause)
</span><span class="cx">                     castedTarget-&gt;pause();
</span><ins>+
+                RemoteInspector::singleton().updateTargetListing(targetIdentifier);
</ins><span class="cx">             } else if (is&lt;RemoteAutomationTarget&gt;(m_target)) {
</span><span class="cx">                 auto castedTarget = downcast&lt;RemoteAutomationTarget&gt;(m_target);
</span><span class="cx">                 castedTarget-&gt;connect(this);
</span><span class="cx">                 m_connected = true;
</span><ins>+
+                RemoteInspector::singleton().updateTargetListing(targetIdentifier);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         deref();
</span><span class="lines">@@ -194,16 +201,19 @@
</span><span class="cx"> 
</span><span class="cx"> void RemoteConnectionToTarget::close()
</span><span class="cx"> {
</span><ins>+    unsigned targetIdentifier = m_target ? m_target-&gt;targetIdentifier() : 0;
+    
</ins><span class="cx">     ref();
</span><span class="cx">     dispatchAsyncOnTarget(^{
</span><span class="cx">         {
</span><span class="cx">             std::lock_guard&lt;Lock&gt; lock(m_targetMutex);
</span><del>-
</del><span class="cx">             if (m_target) {
</span><span class="cx">                 if (m_connected)
</span><span class="cx">                     m_target-&gt;disconnect(this);
</span><span class="cx"> 
</span><span class="cx">                 m_target = nullptr;
</span><ins>+                
+                RemoteInspector::singleton().updateTargetListing(targetIdentifier);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         deref();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorremotecocoaRemoteInspectorCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteInspectorCocoa.mm (213227 => 213228)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteInspectorCocoa.mm        2017-03-01 17:49:59 UTC (rev 213227)
+++ trunk/Source/JavaScriptCore/inspector/remote/cocoa/RemoteInspectorCocoa.mm        2017-03-01 18:03:53 UTC (rev 213228)
</span><span class="lines">@@ -463,6 +463,8 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     m_targetListingMap.set(target.targetIdentifier(), targetListing);
</span><ins>+
+    pushListingsSoon();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #pragma mark - Received XPC Messages
</span><span class="lines">@@ -511,8 +513,6 @@
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="cx"> 
</span><span class="cx">     updateHasActiveDebugSession();
</span><del>-    updateTargetListing(*target);
-    pushListingsSoon();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteInspector::receivedDataMessage(NSDictionary *userInfo)
</span><span class="lines">@@ -551,8 +551,6 @@
</span><span class="cx">     m_targetConnectionMap.remove(targetIdentifier);
</span><span class="cx"> 
</span><span class="cx">     updateHasActiveDebugSession();
</span><del>-    updateTargetListing(targetIdentifier);
-    pushListingsSoon();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteInspector::receivedGetListingMessage(NSDictionary *)
</span><span class="lines">@@ -627,13 +625,10 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     auto connection = it-&gt;value;
</span><del>-    unsigned targetIdentifier = connection-&gt;targetIdentifier().value_or(0);
</del><span class="cx">     connection-&gt;close();
</span><span class="cx">     m_targetConnectionMap.remove(it);
</span><span class="cx"> 
</span><span class="cx">     updateHasActiveDebugSession();
</span><del>-    updateTargetListing(targetIdentifier);
-    pushListingsSoon();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RemoteInspector::receivedAutomaticInspectionConfigurationMessage(NSDictionary *userInfo)
</span></span></pre>
</div>
</div>

</body>
</html>