OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |