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

Side by Side Diff: ipc/ipc_sync_channel_unittest.cc

Issue 9022038: Reimplement ReceivedSyncMsgQueue::DispatchMessages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Try to avoid rescanning entire queue. Added unittest Created 8 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
« ipc/ipc_sync_channel.cc ('K') | « ipc/ipc_sync_channel.cc ('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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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>
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1328 int success = 0; 1328 int success = 0;
1329 std::vector<Worker*> workers; 1329 std::vector<Worker*> workers;
1330 workers.push_back(new NonRestrictedDispatchServer); 1330 workers.push_back(new NonRestrictedDispatchServer);
1331 workers.push_back(server); 1331 workers.push_back(server);
1332 workers.push_back( 1332 workers.push_back(
1333 new RestrictedDispatchClient(&sent_ping_event, server, &success)); 1333 new RestrictedDispatchClient(&sent_ping_event, server, &success));
1334 RunTest(workers); 1334 RunTest(workers);
1335 EXPECT_EQ(3, success); 1335 EXPECT_EQ(3, success);
1336 } 1336 }
1337 1337
1338 //-----------------------------------------------------------------------------
1339
1340 // This test case inspired by crbug.com/108491
1341 // We create two servers that use the same ListenerThread but have
1342 // SetRestrictDispatchToSameChannel set to true.
1343 // We create clients, then use some specific WaitableEvent wait/signalling to
1344 // ensure that messages get dispatched in a way that causes a deadlock due to
1345 // a nested dispatch and an eligible message in a higher-level dispatch's
1346 // delayed_queue.
1347
1348 namespace {
1349
1350 class RestrictedDispatchDeadlockServer : public Worker {
1351 public:
1352 RestrictedDispatchDeadlockServer(int server_num,
1353 WaitableEvent* server_ready_event,
1354 WaitableEvent** events,
1355 RestrictedDispatchDeadlockServer* peer)
1356 : Worker(server_num == 1 ? "channel1" : "channel2", Channel::MODE_SERVER),
1357 server_num_(server_num),
1358 server_ready_event_(server_ready_event),
1359 events_(events),
1360 peer_(peer),
1361 client_kicked_(false) { }
1362
1363 void OnDoServerTask() {
piman 2012/01/10 04:33:17 I was a bit confused about the synchronization. It
Josh Horwich 2012/01/10 20:30:25 Done. Sorry for the brain pain, Your understandin
1364 events_[3]->Signal();
1365 events_[2]->Wait();
1366 events_[0]->Signal();
1367 SendMessageToClient();
1368 }
1369
1370 void Run() {
1371 channel()->SetRestrictDispatchToSameChannel(true);
1372 server_ready_event_->Signal();
1373 }
1374
1375 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1376
1377 private:
1378 bool OnMessageReceived(const Message& message) {
1379 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
1380 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1381 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1382 IPC_END_MESSAGE_MAP()
1383 return true;
1384 }
1385
1386 void OnNoArgs() {
1387 if (server_num_ == 1) {
1388 DCHECK(peer_ != NULL);
1389 peer_->SendMessageToClient();
1390 }
1391 }
1392
1393 void SendMessageToClient() {
1394 Message* msg = new SyncChannelTestMsg_NoArgs;
1395 msg->set_unblock(false);
1396 DCHECK(!msg->should_unblock());
1397 Send(msg);
1398 }
1399
1400 int server_num_;
1401 WaitableEvent* server_ready_event_;
1402 WaitableEvent** events_;
1403 RestrictedDispatchDeadlockServer* peer_;
1404 bool client_kicked_;
1405 };
1406
1407 class RestrictedDispatchDeadlockClient2 : public Worker {
1408 public:
1409 RestrictedDispatchDeadlockClient2(RestrictedDispatchDeadlockServer* server,
1410 WaitableEvent* server_ready_event,
piman 2012/01/10 04:33:17 nit: indentation
Josh Horwich 2012/01/10 20:30:25 Done.
1411 WaitableEvent** events)
1412 : Worker("channel2", Channel::MODE_CLIENT),
piman 2012/01/10 04:33:17 nit: indentation (the : should be an extra 4 space
Josh Horwich 2012/01/10 20:30:25 Done.
1413 server_(server),
1414 server_ready_event_(server_ready_event),
1415 events_(events),
1416 received_msg_(false),
1417 received_noarg_reply_(false),
1418 done_issued_(false) {}
1419
1420 void Run() {
1421 server_ready_event_->Wait();
1422 }
1423
1424 void OnDoClient2Task() {
1425 events_[3]->Wait();
1426 events_[1]->Signal();
1427 events_[2]->Signal();
1428 DCHECK(received_msg_ == false);
1429
1430 Message* message = new SyncChannelTestMsg_NoArgs;
1431 message->set_unblock(true);
1432 Send(message);
1433 received_noarg_reply_ = true;
1434 }
1435
1436 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1437 private:
1438 bool OnMessageReceived(const Message& message) {
1439 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
1440 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1441 IPC_END_MESSAGE_MAP()
1442 return true;
1443 }
1444
1445 void OnNoArgs() {
1446 received_msg_ = true;
1447 PossiblyDone();
1448 }
1449
1450 void PossiblyDone() {
1451 if (received_noarg_reply_ && received_msg_) {
1452 DCHECK(done_issued_ == false);
1453 done_issued_ = true;
1454 Send(new SyncChannelTestMsg_Done);
1455 Done();
1456 }
1457 }
1458
1459 RestrictedDispatchDeadlockServer* server_;
1460 WaitableEvent* server_ready_event_;
1461 WaitableEvent** events_;
1462 bool received_msg_;
1463 bool received_noarg_reply_;
1464 bool done_issued_;
1465 };
1466
1467 class RestrictedDispatchDeadlockClient1 : public Worker {
1468 public:
1469 RestrictedDispatchDeadlockClient1(RestrictedDispatchDeadlockServer* server,
1470 RestrictedDispatchDeadlockClient2* peer,
1471 WaitableEvent* server_ready_event,
1472 WaitableEvent** events)
1473 : Worker("channel1", Channel::MODE_CLIENT),
1474 server_(server),
1475 peer_(peer),
1476 server_ready_event_(server_ready_event),
1477 events_(events),
1478 received_msg_(false),
1479 received_noarg_reply_(false),
1480 done_issued_(false) {}
1481
1482 void Run() {
1483 server_ready_event_->Wait();
1484 server_->ListenerThread()->message_loop()->PostTask(
1485 FROM_HERE,
1486 base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_));
1487 peer_->ListenerThread()->message_loop()->PostTask(
1488 FROM_HERE,
1489 base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_));
1490 events_[0]->Wait();
1491 events_[1]->Wait();
1492 DCHECK(received_msg_ == false);
1493
1494 Message* message = new SyncChannelTestMsg_NoArgs;
1495 message->set_unblock(true);
1496 Send(message);
1497 received_noarg_reply_ = true;
1498 PossiblyDone();
1499 }
1500
1501 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1502 private:
1503 bool OnMessageReceived(const Message& message) {
1504 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
1505 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1506 IPC_END_MESSAGE_MAP()
1507 return true;
1508 }
1509
1510 void OnNoArgs() {
1511 received_msg_ = true;
1512 PossiblyDone();
1513 }
1514
1515 void PossiblyDone() {
1516 if (received_noarg_reply_ && received_msg_) {
1517 DCHECK(done_issued_ == false);
1518 done_issued_ = true;
1519 Send(new SyncChannelTestMsg_Done);
1520 Done();
1521 }
1522 }
1523
1524 RestrictedDispatchDeadlockServer* server_;
1525 RestrictedDispatchDeadlockClient2* peer_;
1526 WaitableEvent* server_ready_event_;
1527 WaitableEvent** events_;
1528 bool received_msg_;
1529 bool received_noarg_reply_;
1530 bool done_issued_;
1531 };
1532
1533 } // namespace
1534
1535 TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
1536 std::vector<Worker*> workers;
1537
1538 // A shared worker thread so that server1 and server2 run on one thread.
1539 base::Thread worker_thread("RestrictedDispatchDeadlock");
1540 ASSERT_TRUE(worker_thread.Start());
1541
1542 WaitableEvent server1_ready(false, false);
1543 WaitableEvent server2_ready(false, false);
1544
1545 WaitableEvent event0(false, false);
1546 WaitableEvent event1(false, false);
1547 WaitableEvent event2(false, false);
1548 WaitableEvent event3(false, false);
1549 WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
1550
1551 RestrictedDispatchDeadlockServer* server1;
1552 RestrictedDispatchDeadlockServer* server2;
1553 RestrictedDispatchDeadlockClient1* client1;
1554 RestrictedDispatchDeadlockClient2* client2;
1555
1556 server2 = new RestrictedDispatchDeadlockServer(2, &server2_ready, events,
1557 NULL);
1558 server2->OverrideThread(&worker_thread);
1559 workers.push_back(server2);
1560
1561 client2 = new RestrictedDispatchDeadlockClient2(server2, &server2_ready,
1562 events);
1563 workers.push_back(client2);
1564
1565 server1 = new RestrictedDispatchDeadlockServer(1, &server1_ready, events,
1566 server2);
1567 server1->OverrideThread(&worker_thread);
1568 workers.push_back(server1);
1569
1570 client1 = new RestrictedDispatchDeadlockClient1(server1, client2,
1571 &server1_ready, events);
1572 workers.push_back(client1);
1573
1574 RunTest(workers);
1575 }
1576
1338 } // namespace IPC 1577 } // namespace IPC
OLDNEW
« ipc/ipc_sync_channel.cc ('K') | « ipc/ipc_sync_channel.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698