OSDN Git Service

Protect the message loop from accesses after HCI shutdown
authorPavlin Radoslavov <pavlin@google.com>
Wed, 17 May 2017 01:50:43 +0000 (18:50 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Thu, 18 May 2017 00:10:57 +0000 (00:10 +0000)
Bug: 38330724
Test: Manual: enable/disable Bluetooth
Change-Id: Iaece4cd608c67b28b436ded9fcc51c0bf28f4098
(cherry picked from commit 7277f39540fefe551dc2120fc4db787a9ed57646)

hci/src/hci_layer.cc

index cb6cd29..f490a91 100644 (file)
@@ -85,6 +85,7 @@ static const packet_fragmenter_t* packet_fragmenter;
 
 static future_t* startup_future;
 static thread_t* thread;  // We own this
+static std::mutex message_loop_mutex;
 static base::MessageLoop* message_loop_ = nullptr;
 static base::RunLoop* run_loop_ = nullptr;
 
@@ -126,6 +127,7 @@ static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
     transmit_fragment, dispatch_reassembled, fragmenter_transmit_finished};
 
 void initialization_complete() {
+  std::lock_guard<std::mutex> lock(message_loop_mutex);
   message_loop_->task_runner()->PostTask(
       FROM_HERE, base::Bind(&event_finish_startup, nullptr));
 }
@@ -154,18 +156,23 @@ void sco_data_received(BT_HDR* packet) {
 static future_t* hci_module_shut_down();
 
 void message_loop_run(UNUSED_ATTR void* context) {
-  message_loop_ = new base::MessageLoop();
-  run_loop_ = new base::RunLoop();
+  {
+    std::lock_guard<std::mutex> lock(message_loop_mutex);
+    message_loop_ = new base::MessageLoop();
+    run_loop_ = new base::RunLoop();
+  }
 
   message_loop_->task_runner()->PostTask(FROM_HERE,
                                          base::Bind(&hci_initialize));
   run_loop_->Run();
 
-  delete message_loop_;
-  message_loop_ = nullptr;
-
-  delete run_loop_;
-  run_loop_ = nullptr;
+  {
+    std::lock_guard<std::mutex> lock(message_loop_mutex);
+    delete message_loop_;
+    message_loop_ = nullptr;
+    delete run_loop_;
+    run_loop_ = nullptr;
+  }
 }
 
 static future_t* hci_module_start_up(void) {
@@ -246,7 +253,10 @@ static future_t* hci_module_shut_down() {
     startup_timer = NULL;
   }
 
-  message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure());
+  {
+    std::lock_guard<std::mutex> lock(message_loop_mutex);
+    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure());
+  }
 
   // Stop the thread to prevent Send() calls.
   if (thread) {
@@ -355,8 +365,15 @@ static void startup_timer_expired(UNUSED_ATTR void* context) {
 static void enqueue_command(waiting_command_t* wait_entry) {
   base::Closure callback = base::Bind(&event_command_ready, wait_entry);
 
-  std::lock_guard<std::mutex> lock(command_credits_mutex);
+  std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex);
   if (command_credits > 0) {
+    std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex);
+    if (message_loop_ == nullptr) {
+      // HCI Layer was shut down
+      buffer_allocator->free(wait_entry->command);
+      osi_free(wait_entry);
+      return;
+    }
     message_loop_->task_runner()->PostTask(FROM_HERE, std::move(callback));
     command_credits--;
   } else {
@@ -377,6 +394,12 @@ static void event_command_ready(waiting_command_t* wait_entry) {
 }
 
 static void enqueue_packet(void* packet) {
+  std::lock_guard<std::mutex> lock(message_loop_mutex);
+  if (message_loop_ == nullptr) {
+    // HCI Layer was shut down
+    buffer_allocator->free(packet);
+    return;
+  }
   message_loop_->task_runner()->PostTask(
       FROM_HERE, base::Bind(&event_packet_ready, packet));
 }
@@ -439,8 +462,13 @@ static void command_timed_out(UNUSED_ATTR void* context) {
 
 // Event/packet receiving functions
 void process_command_credits(int credits) {
-  std::lock_guard<std::mutex> lock(command_credits_mutex);
+  std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex);
+  std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex);
 
+  if (message_loop_ == nullptr) {
+    // HCI Layer was shut down
+    return;
+  }
   command_credits = credits;
   while (command_credits > 0 && command_queue.size() > 0) {
     message_loop_->task_runner()->PostTask(FROM_HERE,