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

Side by Side Diff: base/message_loop/message_loop_task_runner_unittest.cc

Issue 2657603004: Clear PostTaskAndReply task on the destination thread (3) (Closed)
Patch Set: rebase Created 3 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 | base/task/cancelable_task_tracker.h » ('j') | base/task_runner.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/message_loop/message_loop_task_runner.h" 5 #include "base/message_loop/message_loop_task_runner.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order; 101 StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order;
102 102
103 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) { 103 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) {
104 MessageLoop* task_run_on = NULL; 104 MessageLoop* task_run_on = NULL;
105 MessageLoop* task_deleted_on = NULL; 105 MessageLoop* task_deleted_on = NULL;
106 int task_delete_order = -1; 106 int task_delete_order = -1;
107 MessageLoop* reply_run_on = NULL; 107 MessageLoop* reply_run_on = NULL;
108 MessageLoop* reply_deleted_on = NULL; 108 MessageLoop* reply_deleted_on = NULL;
109 int reply_delete_order = -1; 109 int reply_delete_order = -1;
110 110
111 scoped_refptr<LoopRecorder> task_recoder = 111 scoped_refptr<LoopRecorder> task_recorder =
112 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); 112 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
113 scoped_refptr<LoopRecorder> reply_recoder = 113 scoped_refptr<LoopRecorder> reply_recorder =
114 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); 114 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
115 115
116 ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply( 116 ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply(
117 FROM_HERE, Bind(&RecordLoop, task_recoder), 117 FROM_HERE, Bind(&RecordLoop, task_recorder),
118 Bind(&RecordLoopAndQuit, reply_recoder))); 118 Bind(&RecordLoopAndQuit, reply_recorder)));
119 119
120 // Die if base::Bind doesn't retain a reference to the recorders. 120 // Die if base::Bind doesn't retain a reference to the recorders.
121 task_recoder = NULL; 121 task_recorder = NULL;
122 reply_recoder = NULL; 122 reply_recorder = NULL;
123 ASSERT_FALSE(task_deleted_on); 123 ASSERT_FALSE(task_deleted_on);
124 ASSERT_FALSE(reply_deleted_on); 124 ASSERT_FALSE(reply_deleted_on);
125 125
126 UnblockTaskThread(); 126 UnblockTaskThread();
127 RunLoop().Run(); 127 RunLoop().Run();
128 128
129 EXPECT_EQ(task_thread_.message_loop(), task_run_on); 129 EXPECT_EQ(task_thread_.message_loop(), task_run_on);
130 EXPECT_EQ(current_loop_.get(), task_deleted_on); 130 EXPECT_EQ(task_thread_.message_loop(), task_deleted_on);
131 EXPECT_EQ(current_loop_.get(), reply_run_on); 131 EXPECT_EQ(current_loop_.get(), reply_run_on);
132 EXPECT_EQ(current_loop_.get(), reply_deleted_on); 132 EXPECT_EQ(current_loop_.get(), reply_deleted_on);
133 EXPECT_LT(task_delete_order, reply_delete_order); 133 EXPECT_LT(task_delete_order, reply_delete_order);
134 } 134 }
135 135
136 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { 136 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) {
137 MessageLoop* task_run_on = NULL; 137 MessageLoop* task_run_on = NULL;
138 MessageLoop* task_deleted_on = NULL; 138 MessageLoop* task_deleted_on = NULL;
139 int task_delete_order = -1; 139 int task_delete_order = -1;
140 MessageLoop* reply_run_on = NULL; 140 MessageLoop* reply_run_on = NULL;
141 MessageLoop* reply_deleted_on = NULL; 141 MessageLoop* reply_deleted_on = NULL;
142 int reply_delete_order = -1; 142 int reply_delete_order = -1;
143 143
144 scoped_refptr<LoopRecorder> task_recoder = 144 scoped_refptr<LoopRecorder> task_recorder =
145 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); 145 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
146 scoped_refptr<LoopRecorder> reply_recoder = 146 scoped_refptr<LoopRecorder> reply_recorder =
147 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); 147 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
148 148
149 // Grab a task runner to a dead MessageLoop. 149 // Grab a task runner to a dead MessageLoop.
150 scoped_refptr<SingleThreadTaskRunner> task_runner = 150 scoped_refptr<SingleThreadTaskRunner> task_runner =
151 task_thread_.task_runner(); 151 task_thread_.task_runner();
152 UnblockTaskThread(); 152 UnblockTaskThread();
153 task_thread_.Stop(); 153 task_thread_.Stop();
154 154
155 ASSERT_FALSE( 155 ASSERT_FALSE(
156 task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recoder), 156 task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recorder),
157 Bind(&RecordLoopAndQuit, reply_recoder))); 157 Bind(&RecordLoopAndQuit, reply_recorder)));
158 158
159 // The relay should have properly deleted its resources leaving us as the only 159 // The relay should have properly deleted its resources leaving us as the only
160 // reference. 160 // reference.
161 EXPECT_EQ(task_delete_order, reply_delete_order); 161 EXPECT_EQ(task_delete_order, reply_delete_order);
162 ASSERT_TRUE(task_recoder->HasOneRef()); 162 ASSERT_TRUE(task_recorder->HasOneRef());
163 ASSERT_TRUE(reply_recoder->HasOneRef()); 163 ASSERT_TRUE(reply_recorder->HasOneRef());
164 164
165 // Nothing should have run though. 165 // Nothing should have run though.
166 EXPECT_FALSE(task_run_on); 166 EXPECT_FALSE(task_run_on);
167 EXPECT_FALSE(reply_run_on); 167 EXPECT_FALSE(reply_run_on);
168 } 168 }
169 169
170 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) { 170 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) {
171 MessageLoop* task_run_on = NULL; 171 MessageLoop* task_run_on = NULL;
172 MessageLoop* task_deleted_on = NULL; 172 MessageLoop* task_deleted_on = NULL;
173 int task_delete_order = -1; 173 int task_delete_order = -1;
174 MessageLoop* reply_run_on = NULL; 174 MessageLoop* reply_run_on = NULL;
175 MessageLoop* reply_deleted_on = NULL; 175 MessageLoop* reply_deleted_on = NULL;
176 int reply_delete_order = -1; 176 int reply_delete_order = -1;
177 177
178 scoped_refptr<LoopRecorder> task_recoder = 178 scoped_refptr<LoopRecorder> task_recorder =
179 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); 179 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
180 scoped_refptr<LoopRecorder> reply_recoder = 180 scoped_refptr<LoopRecorder> reply_recorder =
181 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); 181 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
182 182
183 // Enqueue the relay. 183 // Enqueue the relay.
184 ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply( 184 ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply(
185 FROM_HERE, Bind(&RecordLoop, task_recoder), 185 FROM_HERE, Bind(&RecordLoop, task_recorder),
186 Bind(&RecordLoopAndQuit, reply_recoder))); 186 Bind(&RecordLoopAndQuit, reply_recorder)));
187 187
188 // Die if base::Bind doesn't retain a reference to the recorders. 188 // Die if base::Bind doesn't retain a reference to the recorders.
189 task_recoder = NULL; 189 task_recorder = NULL;
190 reply_recoder = NULL; 190 reply_recorder = NULL;
191 ASSERT_FALSE(task_deleted_on); 191 ASSERT_FALSE(task_deleted_on);
192 ASSERT_FALSE(reply_deleted_on); 192 ASSERT_FALSE(reply_deleted_on);
193 193
194 RunLoop().Run(); 194 RunLoop().Run();
195 195
196 EXPECT_EQ(current_loop_.get(), task_run_on); 196 EXPECT_EQ(current_loop_.get(), task_run_on);
197 EXPECT_EQ(current_loop_.get(), task_deleted_on); 197 EXPECT_EQ(current_loop_.get(), task_deleted_on);
198 EXPECT_EQ(current_loop_.get(), reply_run_on); 198 EXPECT_EQ(current_loop_.get(), reply_run_on);
199 EXPECT_EQ(current_loop_.get(), reply_deleted_on); 199 EXPECT_EQ(current_loop_.get(), reply_deleted_on);
200 EXPECT_LT(task_delete_order, reply_delete_order); 200 EXPECT_LT(task_delete_order, reply_delete_order);
201 } 201 }
202 202
203 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { 203 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) {
gab 2017/01/31 19:34:59 Rename
dcheng 2017/02/07 07:28:44 Per gab's comment, how about naming this: PostTask
tzik 2017/02/07 08:05:34 Done.
tzik 2017/02/07 08:05:34 Acknowledged.
tzik 2017/02/07 08:33:26 Done.
204 // Annotate the scope as having memory leaks to suppress heapchecker reports. 204 // Annotate the scope as having memory leaks to suppress heapchecker reports.
205 ANNOTATE_SCOPED_MEMORY_LEAK; 205 ANNOTATE_SCOPED_MEMORY_LEAK;
206 MessageLoop* task_run_on = NULL; 206 MessageLoop* task_run_on = NULL;
207 MessageLoop* task_deleted_on = NULL; 207 MessageLoop* task_deleted_on = NULL;
208 int task_delete_order = -1; 208 int task_delete_order = -1;
209 MessageLoop* reply_run_on = NULL; 209 MessageLoop* reply_run_on = NULL;
210 MessageLoop* reply_deleted_on = NULL; 210 MessageLoop* reply_deleted_on = NULL;
211 int reply_delete_order = -1; 211 int reply_delete_order = -1;
212 212
213 scoped_refptr<LoopRecorder> task_recoder = 213 scoped_refptr<LoopRecorder> task_recorder =
214 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); 214 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
215 scoped_refptr<LoopRecorder> reply_recoder = 215 scoped_refptr<LoopRecorder> reply_recorder =
216 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); 216 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
217 217
218 // Enqueue the relay. 218 // Enqueue the relay.
219 task_thread_.task_runner()->PostTaskAndReply( 219 task_thread_.task_runner()->PostTaskAndReply(
220 FROM_HERE, Bind(&RecordLoop, task_recoder), 220 FROM_HERE, Bind(&RecordLoop, task_recorder),
221 Bind(&RecordLoopAndQuit, reply_recoder)); 221 Bind(&RecordLoopAndQuit, reply_recorder));
222 222
223 // Die if base::Bind doesn't retain a reference to the recorders. 223 // Die if base::Bind doesn't retain a reference to the recorders.
224 task_recoder = NULL; 224 task_recorder = NULL;
225 reply_recoder = NULL; 225 reply_recorder = NULL;
226 ASSERT_FALSE(task_deleted_on); 226 ASSERT_FALSE(task_deleted_on);
227 ASSERT_FALSE(reply_deleted_on); 227 ASSERT_FALSE(reply_deleted_on);
228 228
229 UnblockTaskThread(); 229 UnblockTaskThread();
230 230
231 // Mercilessly whack the current loop before |reply| gets to run. 231 // Mercilessly whack the current loop before |reply| gets to run.
232 current_loop_.reset(); 232 current_loop_.reset();
233 233
234 // This should ensure the relay has been run. We need to record the 234 // This should ensure the relay has been run. We need to record the
235 // MessageLoop pointer before stopping the thread because Thread::Stop() will 235 // MessageLoop pointer before stopping the thread because Thread::Stop() will
236 // NULL out its own pointer. 236 // NULL out its own pointer.
237 MessageLoop* task_loop = task_thread_.message_loop(); 237 MessageLoop* task_loop = task_thread_.message_loop();
238 task_thread_.Stop(); 238 task_thread_.Stop();
239 239
240 EXPECT_EQ(task_loop, task_run_on); 240 EXPECT_EQ(task_loop, task_run_on);
dcheng 2017/02/07 07:28:44 And add some comments here to explain the new beha
tzik 2017/02/07 08:05:34 Acknowledged.
tzik 2017/02/07 08:33:26 Done.
241 ASSERT_FALSE(task_deleted_on); 241 EXPECT_EQ(task_loop, task_deleted_on);
242 EXPECT_FALSE(reply_run_on); 242 EXPECT_FALSE(reply_run_on);
243 ASSERT_FALSE(reply_deleted_on); 243 ASSERT_FALSE(reply_deleted_on);
244 EXPECT_EQ(task_delete_order, reply_delete_order);
245 244
246 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to 245 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to
247 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor 246 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor
248 // checks that MessageLoop::current() is the the same as when the 247 // checks that MessageLoop::current() is the the same as when the
249 // PostTaskAndReplyRelay object was constructed. However, this loop must have 248 // PostTaskAndReplyRelay object was constructed. However, this loop must have
250 // already been deleted in order to perform this test. See 249 // already been deleted in order to perform this test. See
251 // http://crbug.com/86301. 250 // http://crbug.com/86301.
252 } 251 }
253 252
254 class MessageLoopTaskRunnerThreadingTest : public testing::Test { 253 class MessageLoopTaskRunnerThreadingTest : public testing::Test {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); 352 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
354 test_thread->Start(); 353 test_thread->Start();
355 task_runner = test_thread->task_runner(); 354 task_runner = test_thread->task_runner();
356 } 355 }
357 bool ret = task_runner->PostTask( 356 bool ret = task_runner->PostTask(
358 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); 357 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
359 EXPECT_FALSE(ret); 358 EXPECT_FALSE(ret);
360 } 359 }
361 360
362 } // namespace base 361 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/task/cancelable_task_tracker.h » ('j') | base/task_runner.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698