Modified: branches/safari-600.2-branch/Source/WebCore/ChangeLog (175009 => 175010)
--- branches/safari-600.2-branch/Source/WebCore/ChangeLog 2014-10-22 01:40:47 UTC (rev 175009)
+++ branches/safari-600.2-branch/Source/WebCore/ChangeLog 2014-10-22 01:44:49 UTC (rev 175010)
@@ -1,5 +1,31 @@
2014-10-21 Dana Burkart <[email protected]>
+ Merge r173848
+
+ 2014-09-22 Alexey Proskuryakov <[email protected]>
+
+ WebSocket crash when a connection is closed from server side
+ https://bugs.webkit.org/show_bug.cgi?id=137009
+ rdar://problem/18333977
+ rdar://problem/12708225
+
+ Reviewed by Brady Eidson.
+
+ I don't think that this can be tested with our test server.
+
+ * Modules/websockets/WebSocketChannel.cpp:
+ (WebCore::WebSocketChannel::WebSocketChannel): Added logging.
+ (WebCore::WebSocketChannel::~WebSocketChannel): Ditto.
+ (WebCore::WebSocketChannel::close): Protect self, because startClosingHandshake
+ can release the last reference.
+ (WebCore::WebSocketChannel::fail): Added an assertion that the channel is always
+ closed after this function.
+ (WebCore::WebSocketChannel::startClosingHandshake): Protect self, and don't change
+ the stack from closed back to closing if after failing to send closing handshake.
+ (WebCore::WebSocketChannel::processOutgoingFrameQueue): Protect self.
+
+2014-10-21 Dana Burkart <[email protected]>
+
Merge r173246
2014-09-03 Myles C. Maxfield <[email protected]>
Modified: branches/safari-600.2-branch/Source/WebCore/Modules/websockets/WebSocketChannel.cpp (175009 => 175010)
--- branches/safari-600.2-branch/Source/WebCore/Modules/websockets/WebSocketChannel.cpp 2014-10-22 01:40:47 UTC (rev 175009)
+++ branches/safari-600.2-branch/Source/WebCore/Modules/websockets/WebSocketChannel.cpp 2014-10-22 01:44:49 UTC (rev 175010)
@@ -85,10 +85,13 @@
{
if (Page* page = m_document->page())
m_identifier = page->progress().createUniqueIdentifier();
+
+ LOG(Network, "WebSocketChannel %p ctor, identifier %lu", this, m_identifier);
}
WebSocketChannel::~WebSocketChannel()
{
+ LOG(Network, "WebSocketChannel %p dtor", this);
}
void WebSocketChannel::connect(const URL& url, const String& protocol)
@@ -181,6 +184,7 @@
ASSERT(!m_suspended);
if (!m_handle)
return;
+ Ref<WebSocketChannel> protect(*this); // An attempt to send closing handshake may fail, which will get the channel closed and dereferenced.
startClosingHandshake(code, reason);
if (m_closing && !m_closingTimer.isActive())
m_closingTimer.startOneShot(2 * TCPMaximumSegmentLifetime);
@@ -208,6 +212,8 @@
if (m_handle && !m_closed)
m_handle->disconnect(); // Will call didClose().
+
+ ASSERT(m_closed);
}
void WebSocketChannel::disconnect()
@@ -458,6 +464,7 @@
void WebSocketChannel::startClosingHandshake(int code, const String& reason)
{
LOG(Network, "WebSocketChannel %p startClosingHandshake() code=%d m_receivedClosingHandshake=%d", this, m_closing, m_receivedClosingHandshake);
+ ASSERT(!m_closed);
if (m_closing)
return;
ASSERT(m_handle);
@@ -471,8 +478,14 @@
buf.append(reason.utf8().data(), reason.utf8().length());
}
enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size());
+ Ref<WebSocketChannel> protect(*this); // An attempt to send closing handshake may fail, which will get the channel closed and dereferenced.
processOutgoingFrameQueue();
+ if (m_closed) {
+ // The channel got closed because processOutgoingFrameQueue() failed.
+ return;
+ }
+
m_closing = true;
if (m_client)
m_client->didStartClosingHandshake();
@@ -706,6 +719,8 @@
if (m_outgoingFrameQueueStatus == OutgoingFrameQueueClosed)
return;
+ Ref<WebSocketChannel> protect(*this); // Any call to fail() will get the channel closed and dereferenced.
+
while (!m_outgoingFrameQueue.isEmpty()) {
OwnPtr<QueuedFrame> frame = m_outgoingFrameQueue.takeFirst();
switch (frame->frameType) {