Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: net/base/host_resolver.cc

Issue 19534: Fix HostResolver crash when MessageLoop is destroyed during (Closed)
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/host_resolver.h" 5 #include "net/base/host_resolver.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <ws2tcpip.h> 8 #include <ws2tcpip.h>
9 #include <wspiapi.h> // Needed for Win2k compat. 9 #include <wspiapi.h> // Needed for Win2k compat.
10 #elif defined(OS_POSIX) 10 #elif defined(OS_POSIX)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 if (mapper) { 56 if (mapper) {
57 rv = HostResolverProc(mapper->Map(host), port, out); 57 rv = HostResolverProc(mapper->Map(host), port, out);
58 } else { 58 } else {
59 rv = HostResolverProc(host, port, out); 59 rv = HostResolverProc(host, port, out);
60 } 60 }
61 return rv; 61 return rv;
62 } 62 }
63 63
64 //----------------------------------------------------------------------------- 64 //-----------------------------------------------------------------------------
65 65
66 class HostResolver::Request : 66 class HostResolver::Request
67 public base::RefCountedThreadSafe<HostResolver::Request> { 67 : public base::RefCountedThreadSafe<HostResolver::Request>,
68 public MessageLoop::DestructionObserver {
68 public: 69 public:
69 Request(HostResolver* resolver, 70 Request(HostResolver* resolver,
70 const std::string& host, 71 const std::string& host,
71 const std::string& port, 72 const std::string& port,
72 AddressList* addresses, 73 AddressList* addresses,
73 CompletionCallback* callback) 74 CompletionCallback* callback)
74 : host_(host), 75 : host_(host),
75 port_(port), 76 port_(port),
76 resolver_(resolver), 77 resolver_(resolver),
77 addresses_(addresses), 78 addresses_(addresses),
78 callback_(callback), 79 callback_(callback),
79 origin_loop_(MessageLoop::current()), 80 origin_loop_(MessageLoop::current()),
80 host_mapper_(host_mapper), 81 host_mapper_(host_mapper),
81 error_(OK), 82 error_(OK),
82 results_(NULL) { 83 results_(NULL) {
84 MessageLoop::current()->AddDestructionObserver(this);
83 } 85 }
84 86
85 ~Request() { 87 virtual ~Request() {
86 if (results_) 88 if (results_)
87 freeaddrinfo(results_); 89 freeaddrinfo(results_);
88 } 90 }
89 91
90 void DoLookup() { 92 void DoLookup() {
91 // Running on the worker thread 93 // Running on the worker thread
92 error_ = ResolveAddrInfo(host_mapper_, host_, port_, &results_); 94 error_ = ResolveAddrInfo(host_mapper_, host_, port_, &results_);
93 95
94 Task* reply = NewRunnableMethod(this, &Request::DoCallback); 96 Task* reply = NewRunnableMethod(this, &Request::DoCallback);
95 97
96 // The origin loop could go away while we are trying to post to it, so we 98 // The origin loop could go away while we are trying to post to it, so we
97 // need to call its PostTask method inside a lock. See ~HostResolver. 99 // need to call its PostTask method inside a lock. See ~HostResolver.
98 { 100 {
99 AutoLock locked(origin_loop_lock_); 101 AutoLock locked(origin_loop_lock_);
100 if (origin_loop_) { 102 if (origin_loop_) {
101 origin_loop_->PostTask(FROM_HERE, reply); 103 origin_loop_->PostTask(FROM_HERE, reply);
102 reply = NULL; 104 reply = NULL;
103 } 105 }
104 } 106 }
105 107
106 // Does nothing if it got posted. 108 // Does nothing if it got posted.
107 delete reply; 109 delete reply;
108 } 110 }
109 111
110 void DoCallback() { 112 void DoCallback() {
111 // Running on the origin thread. 113 // Running on the origin thread.
112 DCHECK(error_ || results_); 114 DCHECK(error_ || results_);
113 115
116 {
117 AutoLock locked(origin_loop_lock_);
118 if (origin_loop_)
119 origin_loop_->RemoveDestructionObserver(this);
120 }
121
114 // We may have been cancelled! 122 // We may have been cancelled!
115 if (!resolver_) 123 if (!resolver_)
116 return; 124 return;
117 125
118 if (!error_) { 126 if (!error_) {
119 addresses_->Adopt(results_); 127 addresses_->Adopt(results_);
120 results_ = NULL; 128 results_ = NULL;
121 } 129 }
122 130
123 // Drop the resolver's reference to us. Do this before running the 131 // Drop the resolver's reference to us. Do this before running the
124 // callback since the callback might result in the resolver being 132 // callback since the callback might result in the resolver being
125 // destroyed. 133 // destroyed.
126 resolver_->request_ = NULL; 134 resolver_->request_ = NULL;
127 135
128 callback_->Run(error_); 136 callback_->Run(error_);
129 } 137 }
130 138
131 void Cancel() { 139 void Cancel() {
132 resolver_ = NULL; 140 resolver_ = NULL;
133 141
134 AutoLock locked(origin_loop_lock_); 142 AutoLock locked(origin_loop_lock_);
135 origin_loop_ = NULL; 143 origin_loop_ = NULL;
136 } 144 }
137 145
146 virtual void WillDestroyCurrentMessageLoop() {
147 AutoLock locked(origin_loop_lock_);
148 origin_loop_ = NULL;
149 }
150
138 private: 151 private:
139 // Set on the origin thread, read on the worker thread. 152 // Set on the origin thread, read on the worker thread.
140 std::string host_; 153 std::string host_;
141 std::string port_; 154 std::string port_;
142 155
143 // Only used on the origin thread (where Resolve was called). 156 // Only used on the origin thread (where Resolve was called).
144 HostResolver* resolver_; 157 HostResolver* resolver_;
145 AddressList* addresses_; 158 AddressList* addresses_;
146 CompletionCallback* callback_; 159 CompletionCallback* callback_;
147 160
(...skipping 14 matching lines...) Expand all
162 175
163 //----------------------------------------------------------------------------- 176 //-----------------------------------------------------------------------------
164 177
165 HostResolver::HostResolver() { 178 HostResolver::HostResolver() {
166 #if defined(OS_WIN) 179 #if defined(OS_WIN)
167 EnsureWinsockInit(); 180 EnsureWinsockInit();
168 #endif 181 #endif
169 } 182 }
170 183
171 HostResolver::~HostResolver() { 184 HostResolver::~HostResolver() {
172 if (request_) 185 if (request_) {
173 request_->Cancel(); 186 request_->Cancel();
187 MessageLoop::current()->RemoveDestructionObserver(request_.get());
188 }
174 } 189 }
175 190
176 int HostResolver::Resolve(const std::string& hostname, int port, 191 int HostResolver::Resolve(const std::string& hostname, int port,
177 AddressList* addresses, 192 AddressList* addresses,
178 CompletionCallback* callback) { 193 CompletionCallback* callback) {
179 DCHECK(!request_) << "resolver already in use"; 194 DCHECK(!request_) << "resolver already in use";
180 195
181 const std::string& port_str = IntToString(port); 196 const std::string& port_str = IntToString(port);
182 197
183 // Do a synchronous resolution. 198 // Do a synchronous resolution.
184 if (!callback) { 199 if (!callback) {
185 struct addrinfo* results; 200 struct addrinfo* results;
186 int rv = ResolveAddrInfo(host_mapper, hostname, port_str, &results); 201 int rv = ResolveAddrInfo(host_mapper, hostname, port_str, &results);
187 if (rv == OK) 202 if (rv == OK)
188 addresses->Adopt(results); 203 addresses->Adopt(results);
189 return rv; 204 return rv;
190 } 205 }
191 206
192 request_ = new Request(this, hostname, port_str, addresses, callback); 207 request_ = new Request(this, hostname, port_str, addresses, callback);
193 208
194 // Dispatch to worker thread... 209 // Dispatch to worker thread...
195 if (!WorkerPool::PostTask(FROM_HERE, 210 if (!WorkerPool::PostTask(FROM_HERE,
196 NewRunnableMethod(request_.get(), &Request::DoLookup), true)) { 211 NewRunnableMethod(request_.get(), &Request::DoLookup), true)) {
197 NOTREACHED(); 212 NOTREACHED();
213 MessageLoop::current()->RemoveDestructionObserver(request_.get());
198 request_ = NULL; 214 request_ = NULL;
199 return ERR_FAILED; 215 return ERR_FAILED;
200 } 216 }
201 217
202 return ERR_IO_PENDING; 218 return ERR_IO_PENDING;
203 } 219 }
204 220
205 } // namespace net 221 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698