Skip to content
Permalink
Browse files
Web Inspector: CRASH in backend at Inspector::HeapFrontendDispatcher:…
…:garbageCollected + 552 when closing frontend/inspected page

https://bugs.webkit.org/show_bug.cgi?id=159075
<rdar://problem/26094341>

Reviewed by Joseph Pecoraro.

Move the asynchronous work to a task class that can be cancelled when the
heap agent is reset, disabled or destroyed.

* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::SendGarbageCollectionEventsTask::SendGarbageCollectionEventsTask):
(Inspector::SendGarbageCollectionEventsTask::addGarbageCollection):
(Inspector::SendGarbageCollectionEventsTask::reset):
(Inspector::SendGarbageCollectionEventsTask::timerFired):
Added. This holds onto GarbageCollection objects that need to be sent asynchronously.
It uses the RunLoop variant of Timer and can queue multiple pending objects to be sent.

(Inspector::InspectorHeapAgent::InspectorHeapAgent):
(Inspector::InspectorHeapAgent::~InspectorHeapAgent):
(Inspector::InspectorHeapAgent::disable):
Reset the task when disabling or tearing down the agent so the timer doesn't fire after destruction.

(Inspector::InspectorHeapAgent::didGarbageCollect):
Send the object to the task to be dispatched asynchronously.

* inspector/agents/InspectorHeapAgent.h:


Canonical link: https://commits.webkit.org/177202@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@202443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
burg committed Jun 24, 2016
1 parent 8f0148b commit 882035d04d974f8ea94f2e2e00f7c099e930bfaf
@@ -1,3 +1,32 @@
2016-06-24 Brian Burg <bburg@apple.com>

Web Inspector: CRASH in backend at Inspector::HeapFrontendDispatcher::garbageCollected + 552 when closing frontend/inspected page
https://bugs.webkit.org/show_bug.cgi?id=159075
<rdar://problem/26094341>

Reviewed by Joseph Pecoraro.

Move the asynchronous work to a task class that can be cancelled when the
heap agent is reset, disabled or destroyed.

* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::SendGarbageCollectionEventsTask::SendGarbageCollectionEventsTask):
(Inspector::SendGarbageCollectionEventsTask::addGarbageCollection):
(Inspector::SendGarbageCollectionEventsTask::reset):
(Inspector::SendGarbageCollectionEventsTask::timerFired):
Added. This holds onto GarbageCollection objects that need to be sent asynchronously.
It uses the RunLoop variant of Timer and can queue multiple pending objects to be sent.

(Inspector::InspectorHeapAgent::InspectorHeapAgent):
(Inspector::InspectorHeapAgent::~InspectorHeapAgent):
(Inspector::InspectorHeapAgent::disable):
Reset the task when disabling or tearing down the agent so the timer doesn't fire after destruction.

(Inspector::InspectorHeapAgent::didGarbageCollect):
Send the object to the task to be dispatched asynchronously.

* inspector/agents/InspectorHeapAgent.h:

2016-06-24 Commit Queue <commit-queue@webkit.org>

Unreviewed, rolling out r202413.
@@ -39,17 +39,61 @@ using namespace JSC;

namespace Inspector {

class SendGarbageCollectionEventsTask {
public:
SendGarbageCollectionEventsTask(HeapFrontendDispatcher&);
void addGarbageCollection(RefPtr<Inspector::Protocol::Heap::GarbageCollection>&&);
void reset();
private:
void timerFired();

HeapFrontendDispatcher& m_frontendDispatcher;
Vector<RefPtr<Inspector::Protocol::Heap::GarbageCollection>> m_garbageCollections;
RunLoop::Timer<SendGarbageCollectionEventsTask> m_timer;
};

SendGarbageCollectionEventsTask::SendGarbageCollectionEventsTask(HeapFrontendDispatcher& frontendDispatcher)
: m_frontendDispatcher(frontendDispatcher)
, m_timer(RunLoop::current(), this, &SendGarbageCollectionEventsTask::timerFired)
{
}

void SendGarbageCollectionEventsTask::addGarbageCollection(RefPtr<Inspector::Protocol::Heap::GarbageCollection>&& garbageCollection)
{
m_garbageCollections.append(WTFMove(garbageCollection));

if (!m_timer.isActive())
m_timer.startOneShot(0);
}

void SendGarbageCollectionEventsTask::reset()
{
m_timer.stop();
m_garbageCollections.clear();
}

void SendGarbageCollectionEventsTask::timerFired()
{
// The timer is stopped on agent destruction, so this method will never be called after agent has been destroyed.
for (auto& event : m_garbageCollections)
m_frontendDispatcher.garbageCollected(event);

m_garbageCollections.clear();
}

InspectorHeapAgent::InspectorHeapAgent(AgentContext& context)
: InspectorAgentBase(ASCIILiteral("Heap"))
, m_injectedScriptManager(context.injectedScriptManager)
, m_frontendDispatcher(std::make_unique<HeapFrontendDispatcher>(context.frontendRouter))
, m_backendDispatcher(HeapBackendDispatcher::create(context.backendDispatcher, this))
, m_environment(context.environment)
, m_sendGarbageCollectionEventsTask(std::make_unique<SendGarbageCollectionEventsTask>(*m_frontendDispatcher))
{
}

InspectorHeapAgent::~InspectorHeapAgent()
{
m_sendGarbageCollectionEventsTask->reset();
}

void InspectorHeapAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
@@ -81,6 +125,7 @@ void InspectorHeapAgent::disable(ErrorString&)
m_enabled = false;

m_environment.vm().heap.removeObserver(this);
m_sendGarbageCollectionEventsTask->reset();

clearHeapSnapshots();
}
@@ -276,25 +321,18 @@ void InspectorHeapAgent::didGarbageCollect(HeapOperation operation)

// FIXME: Include number of bytes freed by collection.

double startTime = m_gcStartTime;
double endTime = m_environment.executionStopwatch()->elapsedTime();

// Dispatch the event asynchronously because this method may be
// called between collection and sweeping and we don't want to
// create unexpected JavaScript allocations that the Sweeper does
// not expect to encounter. JavaScript allocations could happen
// with WebKitLegacy's in process inspector which shares the same
// VM as the inspected page.

RunLoop::current().dispatch([this, startTime, endTime, operation]() {
auto collection = Inspector::Protocol::Heap::GarbageCollection::create()
.setType(protocolTypeForHeapOperation(operation))
.setStartTime(startTime)
.setEndTime(endTime)
.release();

m_frontendDispatcher->garbageCollected(WTFMove(collection));
});
m_sendGarbageCollectionEventsTask->addGarbageCollection(Inspector::Protocol::Heap::GarbageCollection::create()
.setType(protocolTypeForHeapOperation(operation))
.setStartTime(m_gcStartTime)
.setEndTime(m_environment.executionStopwatch()->elapsedTime())
.release());

m_gcStartTime = NAN;
}
@@ -37,6 +37,7 @@
namespace Inspector {

class InjectedScriptManager;
class SendGarbageCollectionEventsTask;
typedef String ErrorString;

class JS_EXPORT_PRIVATE InspectorHeapAgent : public InspectorAgentBase, public HeapBackendDispatcherHandler, public JSC::HeapObserver {
@@ -73,6 +74,8 @@ class JS_EXPORT_PRIVATE InspectorHeapAgent : public InspectorAgentBase, public H
RefPtr<HeapBackendDispatcher> m_backendDispatcher;
InspectorEnvironment& m_environment;

std::unique_ptr<SendGarbageCollectionEventsTask> m_sendGarbageCollectionEventsTask;

bool m_enabled { false };
bool m_tracking { false };
double m_gcStartTime { NAN };

0 comments on commit 882035d

Please sign in to comment.