diff options
author | ukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-03 06:02:25 +0000 |
---|---|---|
committer | ukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-03 06:02:25 +0000 |
commit | c8e62f338255301421ee4b20624d83c777c56a9a (patch) | |
tree | 006144d928d9653b0f81e9f2e5a1ae8c2e385781 /net/socket_stream | |
parent | 91a03874a76bee4d360452c27c96d25a040d917c (diff) | |
download | chromium_src-c8e62f338255301421ee4b20624d83c777c56a9a.zip chromium_src-c8e62f338255301421ee4b20624d83c777c56a9a.tar.gz chromium_src-c8e62f338255301421ee4b20624d83c777c56a9a.tar.bz2 |
Fix WebSocket crash bug.
If SocketStream closes while waiting ResolveProxy, it badly
calls DoResolveProxyComplete from DoLoop invoked by SocketStream::Close,
and real callback of ResolveProxy failed to call SocketStream::OnIOCompleted.
So, don't run DoLoop when closed, if SocketStream is calling APIs of
proxy_service or resolver. Check closing_ after the API calls back
and closes the SocketStream.
BUG=50394,46750
TEST=websocket/tests doesn't crash
Review URL: http://codereview.chromium.org/3054039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54707 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket_stream')
-rw-r--r-- | net/socket_stream/socket_stream.cc | 38 | ||||
-rw-r--r-- | net/socket_stream/socket_stream.h | 2 |
2 files changed, 34 insertions, 6 deletions
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc index fe3afeb..8922096 100644 --- a/net/socket_stream/socket_stream.cc +++ b/net/socket_stream/socket_stream.cc @@ -188,12 +188,23 @@ void SocketStream::Close() { // of AddRef() and Release() in Connect() and Finish(), respectively. if (next_state_ == STATE_NONE) return; - closing_ = true; - // Close asynchronously, so that delegate won't be called - // back before returning Close(). MessageLoop::current()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &SocketStream::DoLoop, OK)); + FROM_HERE, + NewRunnableMethod(this, &SocketStream::DoClose)); +} + +void SocketStream::DoClose() { + closing_ = true; + if (socket_.get()) + socket_->Disconnect(); + // If next_state_ is STATE_READ_WRITE, we'll run DoLoop and close + // the SocketStream. + // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket establishing + // connection, so, we'll close the SocketStream now. + // In other next_state_, we'll wait for callback of other APIs, such as + // ResolveProxy(). + if (next_state_ == STATE_READ_WRITE || next_state_ == STATE_TCP_CONNECT) + DoLoop(ERR_ABORTED); } void SocketStream::RestartWithAuth( @@ -469,6 +480,13 @@ int SocketStream::DoResolveProxyComplete(int result) { // of the proxies in the returned list. return ERR_NO_SUPPORTED_PROXIES; } + if (closing_) { + // We enter STATE_CLOSE here if Close has already been called on this + // SocketStream. We put this if-clause here (not the top of the + // DoResolveProxyComplete method) to process proxy resolving error. + next_state_ = STATE_CLOSE; + return ERR_ABORTED; + } next_state_ = STATE_RESOLVE_HOST; return OK; @@ -506,7 +524,7 @@ int SocketStream::DoResolveHost() { } int SocketStream::DoResolveHostComplete(int result) { - if (result == OK) { + if (result == OK && !closing_) { next_state_ = STATE_TCP_CONNECT; result = delegate_->OnStartOpenConnection(this, &io_callback_); if (result == net::ERR_IO_PENDING) @@ -519,6 +537,10 @@ int SocketStream::DoResolveHostComplete(int result) { } int SocketStream::DoTcpConnect() { + if (closing_) { + next_state_ = STATE_CLOSE; + return ERR_ABORTED; + } next_state_ = STATE_TCP_CONNECT_COMPLETE; DCHECK(factory_); socket_.reset(factory_->CreateTCPClientSocket(addresses_, @@ -528,6 +550,10 @@ int SocketStream::DoTcpConnect() { } int SocketStream::DoTcpConnectComplete(int result) { + if (closing_) { + next_state_ = STATE_CLOSE; + return ERR_ABORTED; + } // TODO(ukai): if error occured, reconsider proxy after error. if (result != OK) { next_state_ = STATE_CLOSE; diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h index 860f785..ed268c2 100644 --- a/net/socket_stream/socket_stream.h +++ b/net/socket_stream/socket_stream.h @@ -220,6 +220,8 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { // Used for WebSocketThrottleTest. void CopyAddrInfo(struct addrinfo* head); + void DoClose(); + // Finishes the job. // Calls OnError and OnClose of delegate, and no more // notifications will be sent to delegate. |