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 1316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1327 int success = 0; | 1327 int success = 0; |
1328 std::vector<Worker*> workers; | 1328 std::vector<Worker*> workers; |
1329 workers.push_back(new NonRestrictedDispatchServer); | 1329 workers.push_back(new NonRestrictedDispatchServer); |
1330 workers.push_back(server); | 1330 workers.push_back(server); |
1331 workers.push_back( | 1331 workers.push_back( |
1332 new RestrictedDispatchClient(&sent_ping_event, server, &success)); | 1332 new RestrictedDispatchClient(&sent_ping_event, server, &success)); |
1333 RunTest(workers); | 1333 RunTest(workers); |
1334 EXPECT_EQ(3, success); | 1334 EXPECT_EQ(3, success); |
1335 } | 1335 } |
1336 | 1336 |
1337 //----------------------------------------------------------------------------- | |
1338 | |
1339 // This test case inspired by crbug.com/108491 | |
1340 // We create two servers that use the same ListenerThread but have | |
1341 // SetRestrictDispatchToSameChannel set to true. | |
1342 // We create clients, then use some specific WaitableEvent wait/signalling to | |
1343 // ensure that messages get dispatched in a way that causes a deadlock due to | |
1344 // a nested dispatch and an eligible message in a higher-level dispatch's | |
1345 // delayed_queue. Specifically, we start with client1 about so send an | |
piman
2012/01/10 20:52:14
typo: "about so send" -> "about to send"
| |
1346 // unblocking message to server1, while the shared listener thread for the | |
1347 // servers server1 and server2 is about to send a non-unblocking message to | |
1348 // client1. At the same time, client2 will be about to send an unblocking | |
1349 // message to server2. Server1 will handle the client1->server1 message by | |
1350 // telling server2 to send a non-unblocking message to client2. | |
1351 // What should happen is that the send to server2 should find the pending, | |
1352 // same-context client2->server2 message to dispatch, causing client2 to | |
1353 // unblock then handle the server2->client2 message, so that the shared | |
1354 // servers' listener thread can then respond to the client1->server1 message. | |
1355 // Then client1 can handle the non-unblocking server1->client1 message. | |
1356 // The old code would end up in a state where the server2->client2 message is | |
1357 // sent, but the client2->server2 message (which is eligible for dispatch, and | |
1358 // which is what client2 is waiting for) is stashed in a local delayed_queue | |
1359 // that has server1's channel context, causing a deadlock. | |
1360 // WaitableEvents in the events array are used to: | |
1361 // event 0: indicate to client1 that server listener is in OnDoServerTask | |
1362 // event 1: indicate to client1 that client2 listener is in OnDoClient2Task | |
1363 // event 2: indicate to server1 that client2 listener is in OnDoClient2Task | |
1364 // event 3: indicate to client2 that server listener is in OnDoServerTask | |
1365 | |
1366 namespace { | |
1367 | |
1368 class RestrictedDispatchDeadlockServer : public Worker { | |
1369 public: | |
1370 RestrictedDispatchDeadlockServer(int server_num, | |
1371 WaitableEvent* server_ready_event, | |
1372 WaitableEvent** events, | |
1373 RestrictedDispatchDeadlockServer* peer) | |
1374 : Worker(server_num == 1 ? "channel1" : "channel2", Channel::MODE_SERVER), | |
1375 server_num_(server_num), | |
1376 server_ready_event_(server_ready_event), | |
1377 events_(events), | |
1378 peer_(peer), | |
1379 client_kicked_(false) { } | |
1380 | |
1381 void OnDoServerTask() { | |
1382 events_[3]->Signal(); | |
1383 events_[2]->Wait(); | |
1384 events_[0]->Signal(); | |
1385 SendMessageToClient(); | |
1386 } | |
1387 | |
1388 void Run() { | |
1389 channel()->SetRestrictDispatchToSameChannel(true); | |
1390 server_ready_event_->Signal(); | |
1391 } | |
1392 | |
1393 base::Thread* ListenerThread() { return Worker::ListenerThread(); } | |
1394 | |
1395 private: | |
1396 bool OnMessageReceived(const Message& message) { | |
1397 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message) | |
1398 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | |
1399 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done) | |
1400 IPC_END_MESSAGE_MAP() | |
1401 return true; | |
1402 } | |
1403 | |
1404 void OnNoArgs() { | |
1405 if (server_num_ == 1) { | |
1406 DCHECK(peer_ != NULL); | |
1407 peer_->SendMessageToClient(); | |
1408 } | |
1409 } | |
1410 | |
1411 void SendMessageToClient() { | |
1412 Message* msg = new SyncChannelTestMsg_NoArgs; | |
1413 msg->set_unblock(false); | |
1414 DCHECK(!msg->should_unblock()); | |
1415 Send(msg); | |
1416 } | |
1417 | |
1418 int server_num_; | |
1419 WaitableEvent* server_ready_event_; | |
1420 WaitableEvent** events_; | |
1421 RestrictedDispatchDeadlockServer* peer_; | |
1422 bool client_kicked_; | |
1423 }; | |
1424 | |
1425 class RestrictedDispatchDeadlockClient2 : public Worker { | |
1426 public: | |
1427 RestrictedDispatchDeadlockClient2(RestrictedDispatchDeadlockServer* server, | |
1428 WaitableEvent* server_ready_event, | |
1429 WaitableEvent** events) | |
1430 : Worker("channel2", Channel::MODE_CLIENT), | |
1431 server_(server), | |
1432 server_ready_event_(server_ready_event), | |
1433 events_(events), | |
1434 received_msg_(false), | |
1435 received_noarg_reply_(false), | |
1436 done_issued_(false) {} | |
1437 | |
1438 void Run() { | |
1439 server_ready_event_->Wait(); | |
1440 } | |
1441 | |
1442 void OnDoClient2Task() { | |
1443 events_[3]->Wait(); | |
1444 events_[1]->Signal(); | |
1445 events_[2]->Signal(); | |
1446 DCHECK(received_msg_ == false); | |
1447 | |
1448 Message* message = new SyncChannelTestMsg_NoArgs; | |
1449 message->set_unblock(true); | |
1450 Send(message); | |
1451 received_noarg_reply_ = true; | |
1452 } | |
1453 | |
1454 base::Thread* ListenerThread() { return Worker::ListenerThread(); } | |
1455 private: | |
1456 bool OnMessageReceived(const Message& message) { | |
1457 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message) | |
1458 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | |
1459 IPC_END_MESSAGE_MAP() | |
1460 return true; | |
1461 } | |
1462 | |
1463 void OnNoArgs() { | |
1464 received_msg_ = true; | |
1465 PossiblyDone(); | |
1466 } | |
1467 | |
1468 void PossiblyDone() { | |
1469 if (received_noarg_reply_ && received_msg_) { | |
1470 DCHECK(done_issued_ == false); | |
1471 done_issued_ = true; | |
1472 Send(new SyncChannelTestMsg_Done); | |
1473 Done(); | |
1474 } | |
1475 } | |
1476 | |
1477 RestrictedDispatchDeadlockServer* server_; | |
1478 WaitableEvent* server_ready_event_; | |
1479 WaitableEvent** events_; | |
1480 bool received_msg_; | |
1481 bool received_noarg_reply_; | |
1482 bool done_issued_; | |
1483 }; | |
1484 | |
1485 class RestrictedDispatchDeadlockClient1 : public Worker { | |
1486 public: | |
1487 RestrictedDispatchDeadlockClient1(RestrictedDispatchDeadlockServer* server, | |
1488 RestrictedDispatchDeadlockClient2* peer, | |
1489 WaitableEvent* server_ready_event, | |
1490 WaitableEvent** events) | |
1491 : Worker("channel1", Channel::MODE_CLIENT), | |
1492 server_(server), | |
1493 peer_(peer), | |
1494 server_ready_event_(server_ready_event), | |
1495 events_(events), | |
1496 received_msg_(false), | |
1497 received_noarg_reply_(false), | |
1498 done_issued_(false) {} | |
1499 | |
1500 void Run() { | |
1501 server_ready_event_->Wait(); | |
1502 server_->ListenerThread()->message_loop()->PostTask( | |
1503 FROM_HERE, | |
1504 base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask, server_)); | |
1505 peer_->ListenerThread()->message_loop()->PostTask( | |
1506 FROM_HERE, | |
1507 base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task, peer_)); | |
1508 events_[0]->Wait(); | |
1509 events_[1]->Wait(); | |
1510 DCHECK(received_msg_ == false); | |
1511 | |
1512 Message* message = new SyncChannelTestMsg_NoArgs; | |
1513 message->set_unblock(true); | |
1514 Send(message); | |
1515 received_noarg_reply_ = true; | |
1516 PossiblyDone(); | |
1517 } | |
1518 | |
1519 base::Thread* ListenerThread() { return Worker::ListenerThread(); } | |
1520 private: | |
1521 bool OnMessageReceived(const Message& message) { | |
1522 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message) | |
1523 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs) | |
1524 IPC_END_MESSAGE_MAP() | |
1525 return true; | |
1526 } | |
1527 | |
1528 void OnNoArgs() { | |
1529 received_msg_ = true; | |
1530 PossiblyDone(); | |
1531 } | |
1532 | |
1533 void PossiblyDone() { | |
1534 if (received_noarg_reply_ && received_msg_) { | |
1535 DCHECK(done_issued_ == false); | |
1536 done_issued_ = true; | |
1537 Send(new SyncChannelTestMsg_Done); | |
1538 Done(); | |
1539 } | |
1540 } | |
1541 | |
1542 RestrictedDispatchDeadlockServer* server_; | |
1543 RestrictedDispatchDeadlockClient2* peer_; | |
1544 WaitableEvent* server_ready_event_; | |
1545 WaitableEvent** events_; | |
1546 bool received_msg_; | |
1547 bool received_noarg_reply_; | |
1548 bool done_issued_; | |
1549 }; | |
1550 | |
1551 } // namespace | |
1552 | |
1553 TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) { | |
1554 std::vector<Worker*> workers; | |
1555 | |
1556 // A shared worker thread so that server1 and server2 run on one thread. | |
1557 base::Thread worker_thread("RestrictedDispatchDeadlock"); | |
1558 ASSERT_TRUE(worker_thread.Start()); | |
1559 | |
1560 WaitableEvent server1_ready(false, false); | |
1561 WaitableEvent server2_ready(false, false); | |
1562 | |
1563 WaitableEvent event0(false, false); | |
1564 WaitableEvent event1(false, false); | |
1565 WaitableEvent event2(false, false); | |
1566 WaitableEvent event3(false, false); | |
1567 WaitableEvent* events[4] = {&event0, &event1, &event2, &event3}; | |
1568 | |
1569 RestrictedDispatchDeadlockServer* server1; | |
1570 RestrictedDispatchDeadlockServer* server2; | |
1571 RestrictedDispatchDeadlockClient1* client1; | |
1572 RestrictedDispatchDeadlockClient2* client2; | |
1573 | |
1574 server2 = new RestrictedDispatchDeadlockServer(2, &server2_ready, events, | |
1575 NULL); | |
1576 server2->OverrideThread(&worker_thread); | |
1577 workers.push_back(server2); | |
1578 | |
1579 client2 = new RestrictedDispatchDeadlockClient2(server2, &server2_ready, | |
1580 events); | |
1581 workers.push_back(client2); | |
1582 | |
1583 server1 = new RestrictedDispatchDeadlockServer(1, &server1_ready, events, | |
1584 server2); | |
1585 server1->OverrideThread(&worker_thread); | |
1586 workers.push_back(server1); | |
1587 | |
1588 client1 = new RestrictedDispatchDeadlockClient1(server1, client2, | |
1589 &server1_ready, events); | |
1590 workers.push_back(client1); | |
1591 | |
1592 RunTest(workers); | |
1593 } | |
1594 | |
1337 } // namespace IPC | 1595 } // namespace IPC |
OLD | NEW |