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

Side by Side Diff: mojo/public/cpp/bindings/lib/multiplex_router.cc

Issue 2666423002: Assert sequence validity on non-thread-safe RefCount manipulations (2) (Closed)
Patch Set: rebase on ImageStorage fix Created 3 years, 10 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" 5 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 420 }
421 421
422 InterfaceId MultiplexRouter::AssociateInterface( 422 InterfaceId MultiplexRouter::AssociateInterface(
423 ScopedInterfaceEndpointHandle handle_to_send) { 423 ScopedInterfaceEndpointHandle handle_to_send) {
424 if (!handle_to_send.pending_association()) 424 if (!handle_to_send.pending_association())
425 return kInvalidInterfaceId; 425 return kInvalidInterfaceId;
426 426
427 uint32_t id = 0; 427 uint32_t id = 0;
428 { 428 {
429 MayAutoLock locker(lock_.get()); 429 MayAutoLock locker(lock_.get());
430 // Relax the cross-thread access restriction to non-thread-safe RefCount.
431 // The lock above protects |endpoint|.
432 base::ScopedAllowCrossThreadRefCountAccess
433 allow_cross_thread_ref_count_access;
430 do { 434 do {
431 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask) 435 if (next_interface_id_value_ >= kInterfaceIdNamespaceMask)
432 next_interface_id_value_ = 1; 436 next_interface_id_value_ = 1;
433 id = next_interface_id_value_++; 437 id = next_interface_id_value_++;
434 if (set_interface_id_namespace_bit_) 438 if (set_interface_id_namespace_bit_)
435 id |= kInterfaceIdNamespaceMask; 439 id |= kInterfaceIdNamespaceMask;
436 } while (base::ContainsKey(endpoints_, id)); 440 } while (base::ContainsKey(endpoints_, id));
437 441
438 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id); 442 InterfaceEndpoint* endpoint = new InterfaceEndpoint(this, id);
439 endpoints_[id] = endpoint; 443 endpoints_[id] = endpoint;
(...skipping 17 matching lines...) Expand all
457 } 461 }
458 return id; 462 return id;
459 } 463 }
460 464
461 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle( 465 ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle(
462 InterfaceId id) { 466 InterfaceId id) {
463 if (!IsValidInterfaceId(id)) 467 if (!IsValidInterfaceId(id))
464 return ScopedInterfaceEndpointHandle(); 468 return ScopedInterfaceEndpointHandle();
465 469
466 MayAutoLock locker(lock_.get()); 470 MayAutoLock locker(lock_.get());
471 // Relax the cross-thread access restriction to non-thread-safe RefCount.
472 // The lock above protects |endpoint|.
473 base::ScopedAllowCrossThreadRefCountAccess
474 allow_cross_thread_ref_count_access;
467 bool inserted = false; 475 bool inserted = false;
468 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); 476 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
469 if (inserted) { 477 if (inserted) {
470 DCHECK(!endpoint->handle_created()); 478 DCHECK(!endpoint->handle_created());
471 479
472 if (encountered_error_) 480 if (encountered_error_)
473 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 481 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED);
474 } else { 482 } else {
475 // If the endpoint already exist, it is because we have received a 483 // If the endpoint already exist, it is because we have received a
476 // notification that the peer endpoint has closed. 484 // notification that the peer endpoint has closed.
477 CHECK(!endpoint->closed()); 485 CHECK(!endpoint->closed());
478 CHECK(endpoint->peer_closed()); 486 CHECK(endpoint->peer_closed());
479 487
480 if (endpoint->handle_created()) 488 if (endpoint->handle_created())
481 return ScopedInterfaceEndpointHandle(); 489 return ScopedInterfaceEndpointHandle();
482 } 490 }
483 491
484 endpoint->set_handle_created(); 492 endpoint->set_handle_created();
485 return CreateScopedInterfaceEndpointHandle(id); 493 return CreateScopedInterfaceEndpointHandle(id);
486 } 494 }
487 495
488 void MultiplexRouter::CloseEndpointHandle( 496 void MultiplexRouter::CloseEndpointHandle(
489 InterfaceId id, 497 InterfaceId id,
490 const base::Optional<DisconnectReason>& reason) { 498 const base::Optional<DisconnectReason>& reason) {
491 if (!IsValidInterfaceId(id)) 499 if (!IsValidInterfaceId(id))
492 return; 500 return;
493 501
494 MayAutoLock locker(lock_.get()); 502 MayAutoLock locker(lock_.get());
503 // Relax the cross-thread access restriction to non-thread-safe RefCount.
504 // The lock above protects |endpoint|.
505 base::ScopedAllowCrossThreadRefCountAccess
506 allow_cross_thread_ref_count_access;
495 DCHECK(base::ContainsKey(endpoints_, id)); 507 DCHECK(base::ContainsKey(endpoints_, id));
496 InterfaceEndpoint* endpoint = endpoints_[id].get(); 508 InterfaceEndpoint* endpoint = endpoints_[id].get();
497 DCHECK(!endpoint->client()); 509 DCHECK(!endpoint->client());
498 DCHECK(!endpoint->closed()); 510 DCHECK(!endpoint->closed());
499 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED); 511 UpdateEndpointStateMayRemove(endpoint, ENDPOINT_CLOSED);
500 512
501 if (!IsMasterInterfaceId(id) || reason) { 513 if (!IsMasterInterfaceId(id) || reason) {
502 MayAutoUnlock unlocker(lock_.get()); 514 MayAutoUnlock unlocker(lock_.get());
503 control_message_proxy_.NotifyPeerEndpointClosed(id, reason); 515 control_message_proxy_.NotifyPeerEndpointClosed(id, reason);
504 } 516 }
505 517
506 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); 518 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr);
507 } 519 }
508 520
509 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient( 521 InterfaceEndpointController* MultiplexRouter::AttachEndpointClient(
510 const ScopedInterfaceEndpointHandle& handle, 522 const ScopedInterfaceEndpointHandle& handle,
511 InterfaceEndpointClient* client, 523 InterfaceEndpointClient* client,
512 scoped_refptr<base::SingleThreadTaskRunner> runner) { 524 scoped_refptr<base::SingleThreadTaskRunner> runner) {
513 const InterfaceId id = handle.id(); 525 const InterfaceId id = handle.id();
514 526
515 DCHECK(IsValidInterfaceId(id)); 527 DCHECK(IsValidInterfaceId(id));
516 DCHECK(client); 528 DCHECK(client);
517 529
518 MayAutoLock locker(lock_.get()); 530 MayAutoLock locker(lock_.get());
531 // Relax the cross-thread access restriction to non-thread-safe RefCount.
532 // The lock above protects |endpoint|.
533 base::ScopedAllowCrossThreadRefCountAccess
534 allow_cross_thread_ref_count_access;
519 DCHECK(base::ContainsKey(endpoints_, id)); 535 DCHECK(base::ContainsKey(endpoints_, id));
520 536
521 InterfaceEndpoint* endpoint = endpoints_[id].get(); 537 InterfaceEndpoint* endpoint = endpoints_[id].get();
522 endpoint->AttachClient(client, std::move(runner)); 538 endpoint->AttachClient(client, std::move(runner));
523 539
524 if (endpoint->peer_closed()) 540 if (endpoint->peer_closed())
525 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); 541 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint));
526 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr); 542 ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr);
527 543
528 return endpoint; 544 return endpoint;
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 // No need to trigger a ProcessTasks() because it is already on the stack. 694 // No need to trigger a ProcessTasks() because it is already on the stack.
679 695
680 return true; 696 return true;
681 } 697 }
682 698
683 void MultiplexRouter::OnPipeConnectionError() { 699 void MultiplexRouter::OnPipeConnectionError() {
684 DCHECK(thread_checker_.CalledOnValidThread()); 700 DCHECK(thread_checker_.CalledOnValidThread());
685 701
686 scoped_refptr<MultiplexRouter> protector(this); 702 scoped_refptr<MultiplexRouter> protector(this);
687 MayAutoLock locker(lock_.get()); 703 MayAutoLock locker(lock_.get());
704 // Relax the cross-thread access restriction to non-thread-safe RefCount.
705 // The lock above protects |endpoint|.
706 base::ScopedAllowCrossThreadRefCountAccess
707 allow_cross_thread_ref_count_access;
688 708
689 encountered_error_ = true; 709 encountered_error_ = true;
690 710
691 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { 711 for (auto iter = endpoints_.begin(); iter != endpoints_.end();) {
692 InterfaceEndpoint* endpoint = iter->second.get(); 712 InterfaceEndpoint* endpoint = iter->second.get();
693 // Increment the iterator before calling UpdateEndpointStateMayRemove() 713 // Increment the iterator before calling UpdateEndpointStateMayRemove()
694 // because it may remove the corresponding value from the map. 714 // because it may remove the corresponding value from the map.
695 ++iter; 715 ++iter;
696 716
697 if (endpoint->client()) 717 if (endpoint->client())
698 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint)); 718 tasks_.push_back(Task::CreateNotifyErrorTask(endpoint));
699 719
700 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED); 720 UpdateEndpointStateMayRemove(endpoint, PEER_ENDPOINT_CLOSED);
701 } 721 }
702 722
703 ProcessTasks(connector_.during_sync_handle_watcher_callback() 723 ProcessTasks(connector_.during_sync_handle_watcher_callback()
704 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES 724 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES
705 : ALLOW_DIRECT_CLIENT_CALLS, 725 : ALLOW_DIRECT_CLIENT_CALLS,
706 connector_.task_runner()); 726 connector_.task_runner());
707 } 727 }
708 728
709 void MultiplexRouter::ProcessTasks( 729 void MultiplexRouter::ProcessTasks(
710 ClientCallBehavior client_call_behavior, 730 ClientCallBehavior client_call_behavior,
711 base::SingleThreadTaskRunner* current_task_runner) { 731 base::SingleThreadTaskRunner* current_task_runner) {
712 AssertLockAcquired(); 732 AssertLockAcquired();
733 // Relax the cross-thread access restriction to non-thread-safe RefCount.
734 // The lock above protects |endpoint|.
735 base::ScopedAllowCrossThreadRefCountAccess
736 allow_cross_thread_ref_count_access;
713 737
714 if (posted_to_process_tasks_) 738 if (posted_to_process_tasks_)
715 return; 739 return;
716 740
717 while (!tasks_.empty() && !paused_) { 741 while (!tasks_.empty() && !paused_) {
718 std::unique_ptr<Task> task(std::move(tasks_.front())); 742 std::unique_ptr<Task> task(std::move(tasks_.front()));
719 tasks_.pop_front(); 743 tasks_.pop_front();
720 744
721 InterfaceId id = kInvalidInterfaceId; 745 InterfaceId id = kInvalidInterfaceId;
722 bool sync_message = 746 bool sync_message =
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 997
974 void MultiplexRouter::AssertLockAcquired() { 998 void MultiplexRouter::AssertLockAcquired() {
975 #if DCHECK_IS_ON() 999 #if DCHECK_IS_ON()
976 if (lock_) 1000 if (lock_)
977 lock_->AssertAcquired(); 1001 lock_->AssertAcquired();
978 #endif 1002 #endif
979 } 1003 }
980 1004
981 } // namespace internal 1005 } // namespace internal
982 } // namespace mojo 1006 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698