Chromium Code Reviews| 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 |