OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/proxy/sync_host_resolver_bridge.h" | 5 #include "net/proxy/sync_host_resolver_bridge.h" |
6 | 6 |
7 #include "base/thread.h" | 7 #include "base/thread.h" |
8 #include "base/waitable_event.h" | 8 #include "base/waitable_event.h" |
9 #include "net/base/address_list.h" | 9 #include "net/base/address_list.h" |
10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
11 #include "net/base/net_log.h" | 11 #include "net/base/net_log.h" |
| 12 #include "net/proxy/multi_threaded_proxy_resolver.h" |
12 #include "net/base/test_completion_callback.h" | 13 #include "net/base/test_completion_callback.h" |
13 #include "net/proxy/proxy_info.h" | 14 #include "net/proxy/proxy_info.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 | 16 |
| 17 // TODO(eroman): This test should be moved into |
| 18 // multi_threaded_proxy_resolver_unittest.cc. |
| 19 |
16 namespace net { | 20 namespace net { |
17 | 21 |
18 namespace { | 22 namespace { |
19 | 23 |
20 // This implementation of HostResolver allows blocking until a resolve request | 24 // This implementation of HostResolver allows blocking until a resolve request |
21 // has been received. The resolve requests it receives will never be completed. | 25 // has been received. The resolve requests it receives will never be completed. |
22 class BlockableHostResolver : public HostResolver { | 26 class BlockableHostResolver : public HostResolver { |
23 public: | 27 public: |
24 BlockableHostResolver() | 28 BlockableHostResolver() |
25 : event_(true, false), | 29 : event_(true, false), |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 private: | 72 private: |
69 // Event to notify when a resolve request was received. | 73 // Event to notify when a resolve request was received. |
70 base::WaitableEvent event_; | 74 base::WaitableEvent event_; |
71 bool was_request_cancelled_; | 75 bool was_request_cancelled_; |
72 }; | 76 }; |
73 | 77 |
74 // This implementation of ProxyResolver simply does a synchronous resolve | 78 // This implementation of ProxyResolver simply does a synchronous resolve |
75 // on |host_resolver| in response to GetProxyForURL(). | 79 // on |host_resolver| in response to GetProxyForURL(). |
76 class SyncProxyResolver : public ProxyResolver { | 80 class SyncProxyResolver : public ProxyResolver { |
77 public: | 81 public: |
78 explicit SyncProxyResolver(HostResolver* host_resolver) | 82 explicit SyncProxyResolver(SyncHostResolverBridge* host_resolver) |
79 : ProxyResolver(false), host_resolver_(host_resolver) {} | 83 : ProxyResolver(false), host_resolver_(host_resolver) {} |
80 | 84 |
81 virtual int GetProxyForURL(const GURL& url, | 85 virtual int GetProxyForURL(const GURL& url, |
82 ProxyInfo* results, | 86 ProxyInfo* results, |
83 CompletionCallback* callback, | 87 CompletionCallback* callback, |
84 RequestHandle* request, | 88 RequestHandle* request, |
85 const BoundNetLog& net_log) { | 89 const BoundNetLog& net_log) { |
86 EXPECT_FALSE(callback); | 90 EXPECT_FALSE(callback); |
87 EXPECT_FALSE(request); | 91 EXPECT_FALSE(request); |
88 | 92 |
89 // Do a synchronous host resolve. | 93 // Do a synchronous host resolve. |
90 HostResolver::RequestInfo info(url.host(), 80); | 94 HostResolver::RequestInfo info(url.host(), 80); |
91 AddressList addresses; | 95 AddressList addresses; |
92 int rv = | 96 int rv = |
93 host_resolver_->Resolve(info, &addresses, NULL, NULL, BoundNetLog()); | 97 host_resolver_->Resolve(info, &addresses, NULL, NULL, BoundNetLog()); |
94 | 98 |
95 EXPECT_EQ(ERR_ABORTED, rv); | 99 EXPECT_EQ(ERR_ABORTED, rv); |
96 | 100 |
97 return rv; | 101 return rv; |
98 } | 102 } |
99 | 103 |
100 virtual void CancelRequest(RequestHandle request) { | 104 virtual void CancelRequest(RequestHandle request) { |
101 NOTREACHED(); | 105 NOTREACHED(); |
102 } | 106 } |
103 | 107 |
| 108 virtual void Shutdown() { |
| 109 host_resolver_->Shutdown(); |
| 110 } |
| 111 |
104 private: | 112 private: |
105 virtual int SetPacScript(const GURL& pac_url, | 113 virtual int SetPacScript(const GURL& pac_url, |
106 const string16& pac_script, | 114 const string16& pac_script, |
107 CompletionCallback* callback) { | 115 CompletionCallback* callback) { |
108 NOTREACHED(); | |
109 return OK; | 116 return OK; |
110 } | 117 } |
111 | 118 |
112 scoped_refptr<HostResolver> host_resolver_; | 119 scoped_refptr<SyncHostResolverBridge> host_resolver_; |
| 120 }; |
| 121 |
| 122 class SyncProxyResolverFactory : public ProxyResolverFactory { |
| 123 public: |
| 124 explicit SyncProxyResolverFactory(SyncHostResolverBridge* sync_host_resolver) |
| 125 : ProxyResolverFactory(false), |
| 126 sync_host_resolver_(sync_host_resolver) { |
| 127 } |
| 128 |
| 129 virtual ProxyResolver* CreateProxyResolver() { |
| 130 return new SyncProxyResolver(sync_host_resolver_); |
| 131 } |
| 132 |
| 133 private: |
| 134 scoped_refptr<SyncHostResolverBridge> sync_host_resolver_; |
113 }; | 135 }; |
114 | 136 |
115 // This helper thread is used to create the circumstances for the deadlock. | 137 // This helper thread is used to create the circumstances for the deadlock. |
116 // It is analagous to the "IO thread" which would be main thread running the | 138 // It is analagous to the "IO thread" which would be main thread running the |
117 // network stack. | 139 // network stack. |
118 class IOThread : public base::Thread { | 140 class IOThread : public base::Thread { |
119 public: | 141 public: |
120 IOThread() : base::Thread("IO-thread") {} | 142 IOThread() : base::Thread("IO-thread") {} |
121 | 143 |
122 virtual ~IOThread() { | 144 virtual ~IOThread() { |
123 Stop(); | 145 Stop(); |
124 } | 146 } |
125 | 147 |
126 const scoped_refptr<BlockableHostResolver>& async_resolver() { | 148 const scoped_refptr<BlockableHostResolver>& async_resolver() { |
127 return async_resolver_; | 149 return async_resolver_; |
128 } | 150 } |
129 | 151 |
130 protected: | 152 protected: |
131 virtual void Init() { | 153 virtual void Init() { |
132 async_resolver_ = new BlockableHostResolver(); | 154 async_resolver_ = new BlockableHostResolver(); |
133 | 155 |
134 // Create a synchronous host resolver that operates the async host | 156 // Create a synchronous host resolver that operates the async host |
135 // resolver on THIS thread. | 157 // resolver on THIS thread. |
136 scoped_refptr<SyncHostResolverBridge> sync_resolver = | 158 scoped_refptr<SyncHostResolverBridge> sync_resolver = |
137 new SyncHostResolverBridge(async_resolver_, message_loop()); | 159 new SyncHostResolverBridge(async_resolver_, message_loop()); |
138 | 160 |
139 proxy_resolver_.reset( | 161 proxy_resolver_.reset( |
140 new SingleThreadedProxyResolverUsingBridgedHostResolver( | 162 new MultiThreadedProxyResolver( |
141 new SyncProxyResolver(sync_resolver), | 163 new SyncProxyResolverFactory(sync_resolver), |
142 sync_resolver)); | 164 1u)); |
| 165 |
| 166 // Initialize the resolver. |
| 167 TestCompletionCallback callback; |
| 168 proxy_resolver_->SetPacScriptByUrl(GURL(), &callback); |
| 169 EXPECT_EQ(OK, callback.WaitForResult()); |
143 | 170 |
144 // Start an asynchronous request to the proxy resolver | 171 // Start an asynchronous request to the proxy resolver |
145 // (note that it will never complete). | 172 // (note that it will never complete). |
146 proxy_resolver_->GetProxyForURL(GURL("http://test/"), &results_, | 173 proxy_resolver_->GetProxyForURL(GURL("http://test/"), &results_, |
147 &callback_, &request_, BoundNetLog()); | 174 &callback_, &request_, BoundNetLog()); |
148 } | 175 } |
149 | 176 |
150 virtual void CleanUp() { | 177 virtual void CleanUp() { |
151 // Cancel the outstanding request (note however that this will not | 178 // Cancel the outstanding request (note however that this will not |
152 // unblock the PAC thread though). | 179 // unblock the PAC thread though). |
153 proxy_resolver_->CancelRequest(request_); | 180 proxy_resolver_->CancelRequest(request_); |
154 | 181 |
155 // Delete the single threaded proxy resolver. | 182 // Delete the single threaded proxy resolver. |
156 proxy_resolver_.reset(); | 183 proxy_resolver_.reset(); |
157 | 184 |
| 185 // (There may have been a completion posted back to origin thread, avoid |
| 186 // leaking it by running). |
| 187 MessageLoop::current()->RunAllPending(); |
| 188 |
158 // During the teardown sequence of the single threaded proxy resolver, | 189 // During the teardown sequence of the single threaded proxy resolver, |
159 // the outstanding host resolve should have been cancelled. | 190 // the outstanding host resolve should have been cancelled. |
160 EXPECT_TRUE(async_resolver_->was_request_cancelled()); | 191 EXPECT_TRUE(async_resolver_->was_request_cancelled()); |
161 | 192 |
162 async_resolver_ = NULL; | 193 async_resolver_ = NULL; |
163 } | 194 } |
164 | 195 |
165 private: | 196 private: |
166 // This (async) host resolver will outlive the thread that is operating it | 197 // This (async) host resolver will outlive the thread that is operating it |
167 // synchronously. | 198 // synchronously. |
168 scoped_refptr<BlockableHostResolver> async_resolver_; | 199 scoped_refptr<BlockableHostResolver> async_resolver_; |
169 | 200 |
170 scoped_ptr<ProxyResolver> proxy_resolver_; | 201 scoped_ptr<ProxyResolver> proxy_resolver_; |
171 | 202 |
172 // Data for the outstanding request to the single threaded proxy resolver. | 203 // Data for the outstanding request to the single threaded proxy resolver. |
173 TestCompletionCallback callback_; | 204 TestCompletionCallback callback_; |
174 ProxyInfo results_; | 205 ProxyInfo results_; |
175 ProxyResolver::RequestHandle request_; | 206 ProxyResolver::RequestHandle request_; |
176 }; | 207 }; |
177 | 208 |
178 // Test that a deadlock does not happen during shutdown when a host resolve | 209 // Test that a deadlock does not happen during shutdown when a host resolve |
179 // is outstanding on the SyncHostResolverBridge. | 210 // is outstanding on the SyncHostResolverBridge. |
180 // This is a regression test for http://crbug.com/41244. | 211 // This is a regression test for http://crbug.com/41244. |
181 TEST(SingleThreadedProxyResolverWithBridgedHostResolverTest, ShutdownDeadlock) { | 212 TEST(MultiThreadedProxyResolverTest, ShutdownIsCalledBeforeThreadJoin) { |
182 IOThread io_thread; | 213 IOThread io_thread; |
183 base::Thread::Options options; | 214 base::Thread::Options options; |
184 options.message_loop_type = MessageLoop::TYPE_IO; | 215 options.message_loop_type = MessageLoop::TYPE_IO; |
185 ASSERT_TRUE(io_thread.StartWithOptions(options)); | 216 ASSERT_TRUE(io_thread.StartWithOptions(options)); |
186 | 217 |
187 io_thread.async_resolver()->WaitUntilRequestIsReceived(); | 218 io_thread.async_resolver()->WaitUntilRequestIsReceived(); |
188 | 219 |
189 // Now upon exitting this scope, the IOThread is destroyed -- this will | 220 // Now upon exitting this scope, the IOThread is destroyed -- this will |
190 // stop the IOThread, which will in turn delete the | 221 // stop the IOThread, which will in turn delete the |
191 // SingleThreadedProxyResolver, which in turn will stop its internal | 222 // SingleThreadedProxyResolver, which in turn will stop its internal |
192 // PAC thread (which is currently blocked waiting on the host resolve which | 223 // PAC thread (which is currently blocked waiting on the host resolve which |
193 // is running on IOThread). The IOThread::Cleanup() will verify that after | 224 // is running on IOThread). The IOThread::Cleanup() will verify that after |
194 // the PAC thread is stopped, it cancels the request on the HostResolver. | 225 // the PAC thread is stopped, it cancels the request on the HostResolver. |
195 } | 226 } |
196 | 227 |
197 } // namespace | 228 } // namespace |
198 | 229 |
199 } // namespace net | 230 } // namespace net |
OLD | NEW |