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

Side by Side Diff: mojo/public/cpp/bindings/tests/associated_interface_unittest.cc

Issue 2608783003: Fix ThreadSafeAssociatedInterfacePtrProvider raciness. (Closed)
Patch Set: Created 3 years, 11 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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h" 15 #include "base/run_loop.h"
16 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
17 #include "base/synchronization/waitable_event.h"
17 #include "base/threading/sequenced_task_runner_handle.h" 18 #include "base/threading/sequenced_task_runner_handle.h"
18 #include "base/threading/thread.h" 19 #include "base/threading/thread.h"
19 #include "base/threading/thread_task_runner_handle.h" 20 #include "base/threading/thread_task_runner_handle.h"
20 #include "mojo/public/cpp/bindings/associated_binding.h" 21 #include "mojo/public/cpp/bindings/associated_binding.h"
21 #include "mojo/public/cpp/bindings/associated_group.h" 22 #include "mojo/public/cpp/bindings/associated_group.h"
22 #include "mojo/public/cpp/bindings/associated_interface_ptr.h" 23 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
23 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" 24 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
24 #include "mojo/public/cpp/bindings/associated_interface_request.h" 25 #include "mojo/public/cpp/bindings/associated_interface_request.h"
25 #include "mojo/public/cpp/bindings/binding.h" 26 #include "mojo/public/cpp/bindings/binding.h"
26 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" 27 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 // Block until the method callback is called on the background thread. 1051 // Block until the method callback is called on the background thread.
1051 run_loop.Run(); 1052 run_loop.Run();
1052 } 1053 }
1053 1054
1054 struct ForwarderTestContext { 1055 struct ForwarderTestContext {
1055 IntegerSenderConnectionPtr connection_ptr; 1056 IntegerSenderConnectionPtr connection_ptr;
1056 std::unique_ptr<IntegerSenderConnectionImpl> interface_impl; 1057 std::unique_ptr<IntegerSenderConnectionImpl> interface_impl;
1057 }; 1058 };
1058 1059
1059 TEST_F(AssociatedInterfaceTest, BindLaterThreadSafeAssociatedInterfacePtr) { 1060 TEST_F(AssociatedInterfaceTest, BindLaterThreadSafeAssociatedInterfacePtr) {
1060 // Create a ThreadSafeAssociatedPtr that we'll bind from a different thread.
1061 scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr =
1062 ThreadSafeIntegerSenderAssociatedPtr::CreateUnbound();
1063
1064 // Start the thread from where we'll bind the interface pointer. 1061 // Start the thread from where we'll bind the interface pointer.
1065 base::Thread other_thread("service test thread"); 1062 base::Thread other_thread("service test thread");
1066 other_thread.Start(); 1063 other_thread.Start();
1067 const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner = 1064 const scoped_refptr<base::SingleThreadTaskRunner>& other_thread_task_runner =
1068 other_thread.message_loop()->task_runner(); 1065 other_thread.message_loop()->task_runner();
1069 ForwarderTestContext* context = new ForwarderTestContext(); 1066 ForwarderTestContext* context = new ForwarderTestContext();
1070 {
1071 base::RunLoop run_loop;
1072 auto run_method = base::Bind(
1073 [](const scoped_refptr<base::TaskRunner>& main_task_runner,
1074 const base::Closure& quit_closure,
1075 const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>&
1076 thread_safe_ptr,
1077 ForwarderTestContext* context) {
1078 // We are on the background thread, create the interface ptr.
1079 context->interface_impl =
1080 base::MakeUnique<IntegerSenderConnectionImpl>(
1081 MakeRequest(&(context->connection_ptr)));
1082 IntegerSenderAssociatedPtr sender;
1083 context->connection_ptr->GetSender(
1084 MakeRequest(&sender, context->connection_ptr.associated_group()));
1085 thread_safe_ptr->Bind(std::move(sender));
1086 main_task_runner->PostTask(FROM_HERE, quit_closure);
1087 },
1088 base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
1089 thread_safe_ptr, context);
1090 1067
1091 other_thread_task_runner->PostTask(FROM_HERE, run_method); 1068 base::WaitableEvent echo_called_event(
1092 // Block until the associated pointer is bound. 1069 base::WaitableEvent::ResetPolicy::MANUAL,
1093 run_loop.Run(); 1070 base::WaitableEvent::InitialState::NOT_SIGNALED);
1094 } 1071
1072 // Create a ThreadSafeAssociatedPtr that we'll bind from a different thread.
1073 scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr =
1074 ThreadSafeIntegerSenderAssociatedPtr::CreateUnbound(
1075 other_thread_task_runner);
1076
1077 base::RunLoop bind_run_loop;
1078 auto run_method = base::Bind(
1079 [](base::WaitableEvent* echo_called_event,
1080 const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>&
1081 thread_safe_ptr,
1082 ForwarderTestContext* context) {
1083 // Wait for echo to be called on the main thread so the interface method
1084 // call happens before the bind.
1085 echo_called_event->Wait();
1086
1087 // We are on the background thread, create the interface ptr.
1088 context->interface_impl =
1089 base::MakeUnique<IntegerSenderConnectionImpl>(
1090 MakeRequest(&(context->connection_ptr)));
1091 IntegerSenderAssociatedPtr sender;
1092 context->connection_ptr->GetSender(
1093 MakeRequest(&sender, context->connection_ptr.associated_group()));
1094 thread_safe_ptr->Bind(std::move(sender));
1095 },
1096 &echo_called_event, thread_safe_ptr, context);
1097
1098 other_thread_task_runner->PostTask(FROM_HERE, run_method);
1095 1099
1096 { 1100 {
1097 // Now we can call methods on the interface from the main thread. 1101 // Now we can call methods on the interface from the main thread.
1098 auto echo_callback = 1102 auto echo_callback =
1099 base::Bind([](const base::Closure& quit_closure, int32_t result) { 1103 base::Bind([](const base::Closure& quit_closure, int32_t result) {
1100 EXPECT_EQ(123, result); 1104 EXPECT_EQ(123, result);
1101 quit_closure.Run(); 1105 quit_closure.Run();
1102 }); 1106 });
1103 base::RunLoop run_loop; 1107 base::RunLoop run_loop;
1104 (*thread_safe_ptr) 1108 (*thread_safe_ptr)
1105 ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure())); 1109 ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure()));
1110
1111 // Let the bind happen on the background thread.
1112 echo_called_event.Signal();
1113
1106 // Block until the method callback is called. 1114 // Block until the method callback is called.
1107 run_loop.Run(); 1115 run_loop.Run();
1108 } 1116 }
1109 1117
1110 other_thread_task_runner->DeleteSoon(FROM_HERE, context); 1118 other_thread_task_runner->DeleteSoon(FROM_HERE, context);
1111 1119
1112 // Reset the pointer now so the InterfacePtr associated resources can be 1120 // Reset the pointer now so the InterfacePtr associated resources can be
1113 // deleted before the background thread's message loop is invalidated. 1121 // deleted before the background thread's message loop is invalidated.
1114 thread_safe_ptr = nullptr; 1122 thread_safe_ptr = nullptr;
1115 } 1123 }
1116 1124
1117 } // namespace 1125 } // namespace
1118 } // namespace test 1126 } // namespace test
1119 } // namespace mojo 1127 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698