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

Side by Side Diff: ipc/ipc_sync_channel_unittest.cc

Issue 11761038: Fix shutdown race in IPCSyncChannelTest and get rid of "suppressions"/annotations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: agh2 Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « ipc/ipc.gyp ('k') | 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) 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 // Unit test for SyncChannel. 5 // Unit test for SyncChannel.
6 6
7 #include "ipc/ipc_sync_channel.h" 7 #include "ipc/ipc_sync_channel.h"
8 8
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/basictypes.h" 12 #include "base/basictypes.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop.h" 16 #include "base/message_loop.h"
17 #include "base/process_util.h" 17 #include "base/process_util.h"
18 #include "base/stl_util.h"
19 #include "base/string_util.h" 18 #include "base/string_util.h"
20 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
21 #include "base/threading/platform_thread.h" 19 #include "base/threading/platform_thread.h"
22 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
23 #include "base/synchronization/waitable_event.h" 21 #include "base/synchronization/waitable_event.h"
24 #include "ipc/ipc_listener.h" 22 #include "ipc/ipc_listener.h"
25 #include "ipc/ipc_message.h" 23 #include "ipc/ipc_message.h"
26 #include "ipc/ipc_sender.h" 24 #include "ipc/ipc_sender.h"
27 #include "ipc/ipc_sync_message_filter.h" 25 #include "ipc/ipc_sync_message_filter.h"
28 #include "ipc/ipc_sync_message_unittest.h" 26 #include "ipc/ipc_sync_message_unittest.h"
29 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
30 28
31 using base::WaitableEvent; 29 using base::WaitableEvent;
32 30
33 namespace IPC { 31 namespace IPC {
34 32
35 namespace { 33 namespace {
36 34
37 // Base class for a "process" with listener and IPC threads. 35 // Base class for a "process" with listener and IPC threads.
38 class Worker : public Listener, public Sender { 36 class Worker : public Listener, public Sender {
39 public: 37 public:
40 // Will create a channel without a name. 38 // Will create a channel without a name.
41 Worker(Channel::Mode mode, const std::string& thread_name) 39 Worker(Channel::Mode mode, const std::string& thread_name)
42 : done_(new WaitableEvent(false, false)), 40 : done_(new WaitableEvent(false, false)),
43 channel_created_(new WaitableEvent(false, false)), 41 channel_created_(new WaitableEvent(false, false)),
44 mode_(mode), 42 mode_(mode),
45 ipc_thread_((thread_name + "_ipc").c_str()), 43 ipc_thread_((thread_name + "_ipc").c_str()),
46 listener_thread_((thread_name + "_listener").c_str()), 44 listener_thread_((thread_name + "_listener").c_str()),
47 overrided_thread_(NULL), 45 overrided_thread_(NULL),
48 shutdown_event_(true, false) { 46 shutdown_event_(true, false),
49 // The data race on vfptr is real but is very hard 47 is_shutdown_(false) {
50 // to suppress using standard Valgrind mechanism (suppressions).
51 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and
52 // make ThreadSanitizer bots green.
53 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841");
54 } 48 }
55 49
56 // Will create a named channel and use this name for the threads' name. 50 // Will create a named channel and use this name for the threads' name.
57 Worker(const std::string& channel_name, Channel::Mode mode) 51 Worker(const std::string& channel_name, Channel::Mode mode)
58 : done_(new WaitableEvent(false, false)), 52 : done_(new WaitableEvent(false, false)),
59 channel_created_(new WaitableEvent(false, false)), 53 channel_created_(new WaitableEvent(false, false)),
60 channel_name_(channel_name), 54 channel_name_(channel_name),
61 mode_(mode), 55 mode_(mode),
62 ipc_thread_((channel_name + "_ipc").c_str()), 56 ipc_thread_((channel_name + "_ipc").c_str()),
63 listener_thread_((channel_name + "_listener").c_str()), 57 listener_thread_((channel_name + "_listener").c_str()),
64 overrided_thread_(NULL), 58 overrided_thread_(NULL),
65 shutdown_event_(true, false) { 59 shutdown_event_(true, false),
66 // The data race on vfptr is real but is very hard 60 is_shutdown_(false) {
67 // to suppress using standard Valgrind mechanism (suppressions).
68 // We have to use ANNOTATE_BENIGN_RACE to hide the reports and
69 // make ThreadSanitizer bots green.
70 ANNOTATE_BENIGN_RACE(this, "Race on vfptr, http://crbug.com/25841");
71 } 61 }
72 62
73 // The IPC thread needs to outlive SyncChannel, so force the correct order of
74 // destruction.
75 virtual ~Worker() { 63 virtual ~Worker() {
76 WaitableEvent listener_done(false, false), ipc_done(false, false); 64 // Shutdown() must be called before destruction.
77 ListenerThread()->message_loop()->PostTask( 65 CHECK(is_shutdown_);
78 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this,
79 &listener_done, &ipc_done));
80 listener_done.Wait();
81 ipc_done.Wait();
82 ipc_thread_.Stop();
83 listener_thread_.Stop();
84 } 66 }
85 void AddRef() { } 67 void AddRef() { }
86 void Release() { } 68 void Release() { }
87 bool Send(Message* msg) { return channel_->Send(msg); } 69 bool Send(Message* msg) { return channel_->Send(msg); }
88 bool SendWithTimeout(Message* msg, int timeout_ms) { 70 bool SendWithTimeout(Message* msg, int timeout_ms) {
89 return channel_->SendWithTimeout(msg, timeout_ms); 71 return channel_->SendWithTimeout(msg, timeout_ms);
90 } 72 }
91 void WaitForChannelCreation() { channel_created_->Wait(); } 73 void WaitForChannelCreation() { channel_created_->Wait(); }
92 void CloseChannel() { 74 void CloseChannel() {
93 DCHECK(MessageLoop::current() == ListenerThread()->message_loop()); 75 DCHECK(MessageLoop::current() == ListenerThread()->message_loop());
94 channel_->Close(); 76 channel_->Close();
95 } 77 }
96 void Start() { 78 void Start() {
97 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT); 79 StartThread(&listener_thread_, MessageLoop::TYPE_DEFAULT);
98 ListenerThread()->message_loop()->PostTask( 80 ListenerThread()->message_loop()->PostTask(
99 FROM_HERE, base::Bind(&Worker::OnStart, this)); 81 FROM_HERE, base::Bind(&Worker::OnStart, this));
100 } 82 }
83 void Shutdown() {
84 // The IPC thread needs to outlive SyncChannel. We can't do this in
85 // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
86 // may result in a race conditions. See http://crbug.com/25841.
87 WaitableEvent listener_done(false, false), ipc_done(false, false);
88 ListenerThread()->message_loop()->PostTask(
89 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown1, this,
90 &listener_done, &ipc_done));
91 listener_done.Wait();
92 ipc_done.Wait();
93 ipc_thread_.Stop();
94 listener_thread_.Stop();
95 is_shutdown_ = true;
96 }
101 void OverrideThread(base::Thread* overrided_thread) { 97 void OverrideThread(base::Thread* overrided_thread) {
102 DCHECK(overrided_thread_ == NULL); 98 DCHECK(overrided_thread_ == NULL);
103 overrided_thread_ = overrided_thread; 99 overrided_thread_ = overrided_thread;
104 } 100 }
105 bool SendAnswerToLife(bool pump, int timeout, bool succeed) { 101 bool SendAnswerToLife(bool pump, int timeout, bool succeed) {
106 int answer = 0; 102 int answer = 0;
107 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer); 103 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
108 if (pump) 104 if (pump)
109 msg->EnableMessagePumping(); 105 msg->EnableMessagePumping();
110 bool result = SendWithTimeout(msg, timeout); 106 bool result = SendWithTimeout(msg, timeout);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 scoped_ptr<WaitableEvent> channel_created_; 225 scoped_ptr<WaitableEvent> channel_created_;
230 std::string channel_name_; 226 std::string channel_name_;
231 Channel::Mode mode_; 227 Channel::Mode mode_;
232 scoped_ptr<SyncChannel> channel_; 228 scoped_ptr<SyncChannel> channel_;
233 base::Thread ipc_thread_; 229 base::Thread ipc_thread_;
234 base::Thread listener_thread_; 230 base::Thread listener_thread_;
235 base::Thread* overrided_thread_; 231 base::Thread* overrided_thread_;
236 232
237 base::WaitableEvent shutdown_event_; 233 base::WaitableEvent shutdown_event_;
238 234
235 bool is_shutdown_;
236
239 DISALLOW_COPY_AND_ASSIGN(Worker); 237 DISALLOW_COPY_AND_ASSIGN(Worker);
240 }; 238 };
241 239
242 240
243 // Starts the test with the given workers. This function deletes the workers 241 // Starts the test with the given workers. This function deletes the workers
244 // when it's done. 242 // when it's done.
245 void RunTest(std::vector<Worker*> workers) { 243 void RunTest(std::vector<Worker*> workers) {
246 // First we create the workers that are channel servers, or else the other 244 // First we create the workers that are channel servers, or else the other
247 // workers' channel initialization might fail because the pipe isn't created.. 245 // workers' channel initialization might fail because the pipe isn't created..
248 for (size_t i = 0; i < workers.size(); ++i) { 246 for (size_t i = 0; i < workers.size(); ++i) {
249 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) { 247 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
250 workers[i]->Start(); 248 workers[i]->Start();
251 workers[i]->WaitForChannelCreation(); 249 workers[i]->WaitForChannelCreation();
252 } 250 }
253 } 251 }
254 252
255 // now create the clients 253 // now create the clients
256 for (size_t i = 0; i < workers.size(); ++i) { 254 for (size_t i = 0; i < workers.size(); ++i) {
257 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG) 255 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
258 workers[i]->Start(); 256 workers[i]->Start();
259 } 257 }
260 258
261 // wait for all the workers to finish 259 // wait for all the workers to finish
262 for (size_t i = 0; i < workers.size(); ++i) 260 for (size_t i = 0; i < workers.size(); ++i)
263 workers[i]->done_event()->Wait(); 261 workers[i]->done_event()->Wait();
264 262
265 STLDeleteContainerPointers(workers.begin(), workers.end()); 263 for (size_t i = 0; i < workers.size(); ++i) {
264 workers[i]->Shutdown();
265 delete workers[i];
266 }
266 } 267 }
267 268
268 } // namespace 269 } // namespace
269 270
270 class IPCSyncChannelTest : public testing::Test { 271 class IPCSyncChannelTest : public testing::Test {
271 private: 272 private:
272 MessageLoop message_loop_; 273 MessageLoop message_loop_;
273 }; 274 };
274 275
275 //----------------------------------------------------------------------------- 276 //-----------------------------------------------------------------------------
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 ServerSendAfterClose server; 1188 ServerSendAfterClose server;
1188 server.Start(); 1189 server.Start();
1189 1190
1190 server.done_event()->Wait(); 1191 server.done_event()->Wait();
1191 server.done_event()->Reset(); 1192 server.done_event()->Reset();
1192 1193
1193 server.SendDummy(); 1194 server.SendDummy();
1194 server.done_event()->Wait(); 1195 server.done_event()->Wait();
1195 1196
1196 EXPECT_FALSE(server.send_result()); 1197 EXPECT_FALSE(server.send_result());
1198
1199 server.Shutdown();
1197 } 1200 }
1198 1201
1199 //----------------------------------------------------------------------------- 1202 //-----------------------------------------------------------------------------
1200 1203
1201 namespace { 1204 namespace {
1202 1205
1203 class RestrictedDispatchServer : public Worker { 1206 class RestrictedDispatchServer : public Worker {
1204 public: 1207 public:
1205 RestrictedDispatchServer(WaitableEvent* sent_ping_event, 1208 RestrictedDispatchServer(WaitableEvent* sent_ping_event,
1206 WaitableEvent* wait_event) 1209 WaitableEvent* wait_event)
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
1956 1959
1957 } // namespace 1960 } // namespace
1958 1961
1959 // Windows needs to send an out-of-band secret to verify the client end of the 1962 // Windows needs to send an out-of-band secret to verify the client end of the
1960 // channel. Test that we still connect correctly in that case. 1963 // channel. Test that we still connect correctly in that case.
1961 TEST_F(IPCSyncChannelTest, Verified) { 1964 TEST_F(IPCSyncChannelTest, Verified) {
1962 Verified(); 1965 Verified();
1963 } 1966 }
1964 1967
1965 } // namespace IPC 1968 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698