Modified: trunk/Source/WebCore/ChangeLog (98693 => 98694)
--- trunk/Source/WebCore/ChangeLog 2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/ChangeLog 2011-10-28 05:39:15 UTC (rev 98694)
@@ -1,3 +1,29 @@
+2011-10-28 Yuta Kitamura <yu...@chromium.org>
+
+ Race condition in SocketStreamHandleCFNet when PAC script is used
+ https://bugs.webkit.org/show_bug.cgi?id=70894
+
+ Reviewed by Alexey Proskuryakov.
+
+ Pass callback functions that call ref() or deref() as retain/release member
+ of CFStreamClientContext.
+
+ No new tests, as it is not possible to write a test with PAC script enabled.
+
+ * platform/network/cf/SocketStreamHandle.h:
+ * platform/network/cf/SocketStreamHandleCFNet.cpp:
+ (WebCore::SocketStreamHandle::scheduleStreams):
+ (WebCore::SocketStreamHandle::retainSocketStreamHandle):
+ (WebCore::SocketStreamHandle::releaseSocketStreamHandle):
+ (WebCore::SocketStreamHandle::pacExecutionCallbackMainThread):
+ This callback may be called after platformClose() is already called. We should
+ not create new streams in this case.
+ (WebCore::SocketStreamHandle::executePACFileURL):
+ (WebCore::SocketStreamHandle::readStreamCallback):
+ This manual ref/deref can be safely removed as m_readStream holds the reference.
+ (WebCore::SocketStreamHandle::writeStreamCallback):
+ Ditto.
+
2011-10-27 Arthur Hsu <arthur...@chromium.org>
Reland patch ensure font load before calling Skia during printing
Modified: trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h (98693 => 98694)
--- trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h 2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/platform/network/cf/SocketStreamHandle.h 2011-10-28 05:39:15 UTC (rev 98694)
@@ -74,7 +74,9 @@
void addCONNECTCredentials(CFHTTPMessageRef response);
- static CFStringRef copyCFStreamDescription(void* );
+ static void* retainSocketStreamHandle(void*);
+ static void releaseSocketStreamHandle(void*);
+ static CFStringRef copyCFStreamDescription(void*);
static void readStreamCallback(CFReadStreamRef, CFStreamEventType, void*);
static void writeStreamCallback(CFWriteStreamRef, CFStreamEventType, void*);
#if PLATFORM(WIN)
Modified: trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp (98693 => 98694)
--- trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp 2011-10-28 05:39:13 UTC (rev 98693)
+++ trunk/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp 2011-10-28 05:39:15 UTC (rev 98694)
@@ -82,7 +82,7 @@
ASSERT(m_readStream);
ASSERT(m_writeStream);
- CFStreamClientContext clientContext = { 0, this, 0, 0, copyCFStreamDescription };
+ CFStreamClientContext clientContext = { 0, this, retainSocketStreamHandle, releaseSocketStreamHandle, copyCFStreamDescription };
// FIXME: Pass specific events we're interested in instead of -1.
CFReadStreamSetClient(m_readStream.get(), static_cast<CFOptionFlags>(-1), readStreamCallback, &clientContext);
CFWriteStreamSetClient(m_writeStream.get(), static_cast<CFOptionFlags>(-1), writeStreamCallback, &clientContext);
@@ -104,6 +104,19 @@
m_connectingSubstate = WaitingForConnect;
}
+void* SocketStreamHandle::retainSocketStreamHandle(void* info)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(info);
+ handle->ref();
+ return handle;
+}
+
+void SocketStreamHandle::releaseSocketStreamHandle(void* info)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(info);
+ handle->deref();
+}
+
CFStringRef SocketStreamHandle::copyPACExecutionDescription(void*)
{
return CFSTR("WebSocket proxy PAC file execution");
@@ -128,6 +141,8 @@
MainThreadPACCallbackInfo* info = static_cast<MainThreadPACCallbackInfo*>(invocation);
ASSERT(info->handle->m_connectingSubstate == ExecutingPACFile);
// This time, the array won't have PAC as a first entry.
+ if (info->handle->m_state != Connecting)
+ return;
info->handle->chooseProxyFromArray(info->proxyList);
info->handle->createStreams();
info->handle->scheduleStreams();
@@ -136,7 +151,7 @@
void SocketStreamHandle::executePACFileURL(CFURLRef pacFileURL)
{
// CFNetwork returns an empty proxy array for WebScoket schemes, so use m_httpsURL.
- CFStreamClientContext clientContext = { 0, this, 0, 0, copyPACExecutionDescription };
+ CFStreamClientContext clientContext = { 0, this, retainSocketStreamHandle, releaseSocketStreamHandle, copyPACExecutionDescription };
m_pacRunLoopSource.adoptCF(CFNetworkExecuteProxyAutoConfigurationURL(pacFileURL, m_httpsURL.get(), pacExecutionCallback, &clientContext));
#if PLATFORM(WIN)
CFRunLoopAddSource(loaderRunLoop(), m_pacRunLoopSource.get(), kCFRunLoopDefaultMode);
@@ -443,8 +458,6 @@
if (m_connectingSubstate == WaitingForConnect) {
m_connectingSubstate = Connected;
m_state = Open;
-
- RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
m_client->didOpenSocketStream(this);
if (m_state == Closed)
break;
@@ -502,8 +515,6 @@
if (m_connectingSubstate == WaitingForConnect) {
m_connectingSubstate = Connected;
m_state = Open;
-
- RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
m_client->didOpenSocketStream(this);
break;
}