AssociatedInterfacePtr on WorkerThread

34 views
Skip to first unread message

Makoto Shimazu

unread,
Oct 31, 2016, 1:28:44 AM10/31/16
to chromium-mojo
Hi members,

I'm trying to mojofy several messages sent from WorkerThread, and I'm planning to use AssociatedInterfacePtr for the messages. However, it crashes by an error of threading violation when discarding the pointer object.
I tried pattern (A) and (B) but both failed as I wrote in the comments.

Could you give me advice to use the AssociatedInterfacePtr on the WorkerThread?
Or do I have to use PostTask to the main thread for each messaging? 

My current understanding is:
1: AssociatedInterfacePtr should be called on the same thread with the thread where the pointer is created (so that I have to create AssociatedPtr on the WorkerThread)
2: Destructor of AssociatedInterfacePtr should be called on the same thread with the constructor is called
3: ChildThreadImpl::current()->channel()->GetRemoteAssociatedInterface() should be called on the main thread due to ChildThreadImpl::current()
4: AssociatedInterfaceRequest can be passed beyond threads, so I can create a request object on the worker thread and pass it to the main thread for GetRemoteAssociatedInterface.
5: However, IPC::ChannelMojo (or IPC::MojoBootstrap) seems to be implemented for only IPCs on the main thread. A DCHECK restricts to call the dtor of AssociatedInterfacePtr on the worker thread.

The followings are the crash dumps for pattern (A) and (B) respectively.

Thanks,
Makoto

-- 

== (A) ==
[1:1:1031/124705:FATAL:interface_endpoint_client.cc(167)] Check failed: thread_checker_.CalledOnValidThread(). 
#0 0x7f9bc28c053e base::debug::StackTrace::StackTrace()
#1 0x7f9bc292fa6f logging::LogMessage::~LogMessage()
#2 0x7f9bc30b096d mojo::InterfaceEndpointClient::~InterfaceEndpointClient()
#3 0x7f9bc30b0ba9 mojo::InterfaceEndpointClient::~InterfaceEndpointClient()
#4 0x7f9bbb7219ef std::default_delete<>::operator()()
#5 0x7f9bbb7ac72c std::unique_ptr<>::reset()
#6 0x7f9bbb8de4ed mojo::internal::AssociatedInterfacePtrState<>::~AssociatedInterfacePtrState()
#7 0x7f9bbb8de3f7 mojo::AssociatedInterfacePtr<>::reset()
#8 0x7f9bbb8ca7e9 content::(anonymous namespace)::DiscardAssociatedPtrOnMainThread()
#9 0x7f9bbb8e31bb _ZN4base8internal13FunctorTraitsIPFvN4mojo22AssociatedInterfacePtrIN7content5mojom27ServiceWorkerDispatcherHostEEEEvE6InvokeIJS7_EEEvS9_DpOT_
#10 0x7f9bbb8e3108 _ZN4base8internal12InvokeHelperILb0EvE8MakeItSoIRKPFvN4mojo22AssociatedInterfacePtrIN7content5mojom27ServiceWorkerDispatcherHostEEEEJS9_EEEvOT_DpOT0_
#11 0x7f9bbb8e309b _ZN4base8internal7InvokerINS0_9BindStateIPFvN4mojo22AssociatedInterfacePtrIN7content5mojom27ServiceWorkerDispatcherHostEEEEJNS0_13PassedWrapperIS8_EEEEEFvvEE7RunImplIRKSA_RKSt5tupleIJSC_EEJLm0EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEE
#12 0x7f9bbb8e2fcc _ZN4base8internal7InvokerINS0_9BindStateIPFvN4mojo22AssociatedInterfacePtrIN7content5mojom27ServiceWorkerDispatcherHostEEEEJNS0_13PassedWrapperIS8_EEEEEFvvEE3RunEPNS0_13BindStateBaseE
#13 0x7f9bc28c6421 _ZNO4base8internal8RunMixinINS_8CallbackIFvvELNS0_8CopyModeE0ELNS0_10RepeatModeE0EEEE3RunEv
#14 0x7f9bc28c5e29 base::debug::TaskAnnotator::RunTask()
#15 0x7f9bb3961e01 blink::scheduler::TaskQueueManager::ProcessTaskFromWorkQueue()
#16 0x7f9bb395f782 blink::scheduler::TaskQueueManager::DoWork()
#17 0x7f9bb396826c _ZN4base8internal13FunctorTraitsIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEvE6InvokeIRKNS_7WeakPtrIS4_EEJRKS5_RKbEEEvS7_OT_DpOT0_
#18 0x7f9bb3968114 _ZN4base8internal12InvokeHelperILb1EvE8MakeItSoIRKMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbERKNS_7WeakPtrIS6_EEJRKS7_RKbEEEvOT_OT0_DpOT1_
#19 0x7f9bb3968074 _ZN4base8internal7InvokerINS0_9BindStateIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEJNS_7WeakPtrIS5_EES6_bEEEFvvEE7RunImplIRKS8_RKSt5tupleIJSA_S6_bEEJLm0ELm1ELm2EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEE
#20 0x7f9bb3967f4c _ZN4base8internal7InvokerINS0_9BindStateIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEJNS_7WeakPtrIS5_EES6_bEEEFvvEE3RunEPNS0_13BindStateBaseE
#21 0x7f9bc28c6421 _ZNO4base8internal8RunMixinINS_8CallbackIFvvELNS0_8CopyModeE0ELNS0_10RepeatModeE0EEEE3RunEv
#22 0x7f9bc28c5e29 base::debug::TaskAnnotator::RunTask()
#23 0x7f9bc295892a base::MessageLoop::RunTask()
#24 0x7f9bc2958bb4 base::MessageLoop::DeferOrRunPendingTask()
#25 0x7f9bc2958e9e base::MessageLoop::DoWork()
#26 0x7f9bc29707f3 base::MessagePumpDefault::Run()
#27 0x7f9bc29584aa base::MessageLoop::RunHandler()
#28 0x7f9bc29fdfe4 base::RunLoop::Run()
#29 0x7f9bbd529d6c content::RendererMain()
#30 0x7f9bbd8f5e3e content::RunZygote()
#31 0x7f9bbd8f6250 content::RunNamedProcessTypeMain()
#32 0x7f9bbd8f82b2 content::ContentMainRunnerImpl::Run()
#33 0x7f9bbd8f54e2 content::ContentMain()
#34 0x7f9bc37348ab ChromeMain
#35 0x7f9bc3734842 main
#36 0x7f9bafc2af45 __libc_start_main
#37 0x7f9bc3734745 <unknown>


== (B) ==
[1:10:1031/124843:FATAL:ipc_mojo_bootstrap.cc(489)] Check failed: proxy_task_runner_->BelongsToCurrentThread(). 
#0 0x7f207390d53e base::debug::StackTrace::StackTrace()
#1 0x7f207397ca6f logging::LogMessage::~LogMessage()
#2 0x7f20708d0bbb IPC::(anonymous namespace)::ChannelAssociatedGroupController::SendMessage()
#3 0x7f20708d0911 IPC::(anonymous namespace)::ChannelAssociatedGroupController::ControlMessageProxyThunk::Accept()
#4 0x7f2074124448 mojo::(anonymous namespace)::SendRunOrClosePipeMessage()
#5 0x7f20741242fa mojo::PipeControlMessageProxy::NotifyPeerEndpointClosed()
#6 0x7f20708ceedc IPC::(anonymous namespace)::ChannelAssociatedGroupController::CloseEndpointHandle()
#7 0x7f207412e43d mojo::ScopedInterfaceEndpointHandle::reset()
#8 0x7f207412e3c9 mojo::ScopedInterfaceEndpointHandle::~ScopedInterfaceEndpointHandle()
#9 0x7f20740fdada mojo::InterfaceEndpointClient::~InterfaceEndpointClient()
#10 0x7f20740fdba9 mojo::InterfaceEndpointClient::~InterfaceEndpointClient()
#11 0x7f206c76f9ef std::default_delete<>::operator()()
#12 0x7f206c7fa72c std::unique_ptr<>::reset()
#13 0x7f206c92c3dd mojo::internal::AssociatedInterfacePtrState<>::~AssociatedInterfacePtrState()
#14 0x7f206c924d37 mojo::AssociatedInterfacePtr<>::reset()
#15 0x7f206c9185a3 content::ServiceWorkerDispatcher::~ServiceWorkerDispatcher()
#16 0x7f206c918749 content::ServiceWorkerDispatcher::~ServiceWorkerDispatcher()
#17 0x7f206c920eab content::ServiceWorkerDispatcher::WillStopCurrentWorkerThread()
#18 0x7f206c991e17 content::WorkerThreadRegistry::WillStopCurrentWorkerThread()
#19 0x7f206c801669 content::BlinkPlatformImpl::willStopWorkerThread()
#20 0x7f205b47123f blink::WorkerBackingThread::shutdown()
#21 0x7f205b48e222 blink::WorkerThread::performShutdownOnWorkerThread()
#22 0x7f205a9d1395 _ZN4base8internal13FunctorTraitsIMN5blink8Resource16ResourceCallbackEFvvEvE6InvokeIPS4_JEEEvS6_OT_DpOT0_
#23 0x7f205b497011 _ZN4base8internal12InvokeHelperILb0EvE8MakeItSoIRKMN5blink12WorkerThreadEFvvEJPS5_EEEvOT_DpOT0_
#24 0x7f205b496fb7 _ZN4base8internal7InvokerINS0_9BindStateIMN5blink12WorkerThreadEFvvEJN3WTF17UnretainedWrapperIS4_LNS7_22FunctionThreadAffinityE0EEEEEEFvvEE7RunImplIRKS6_RKSt5tupleIJSA_EEJLm0EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEE
#25 0x7f205b496efc _ZN4base8internal7InvokerINS0_9BindStateIMN5blink12WorkerThreadEFvvEJN3WTF17UnretainedWrapperIS4_LNS7_22FunctionThreadAffinityE0EEEEEEFvvEE3RunEPNS0_13BindStateBaseE
#26 0x7f2073913421 _ZNO4base8internal8RunMixinINS_8CallbackIFvvELNS0_8CopyModeE0ELNS0_10RepeatModeE0EEEE3RunEv
#27 0x7f2073912e29 base::debug::TaskAnnotator::RunTask()
#28 0x7f20649afe01 blink::scheduler::TaskQueueManager::ProcessTaskFromWorkQueue()
#29 0x7f20649ad782 blink::scheduler::TaskQueueManager::DoWork()
#30 0x7f20649b626c _ZN4base8internal13FunctorTraitsIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEvE6InvokeIRKNS_7WeakPtrIS4_EEJRKS5_RKbEEEvS7_OT_DpOT0_
#31 0x7f20649b6114 _ZN4base8internal12InvokeHelperILb1EvE8MakeItSoIRKMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbERKNS_7WeakPtrIS6_EEJRKS7_RKbEEEvOT_OT0_DpOT1_
#32 0x7f20649b6074 _ZN4base8internal7InvokerINS0_9BindStateIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEJNS_7WeakPtrIS5_EES6_bEEEFvvEE7RunImplIRKS8_RKSt5tupleIJSA_S6_bEEJLm0ELm1ELm2EEEEvOT_OT0_NS_13IndexSequenceIJXspT1_EEEE
#33 0x7f20649b5f4c _ZN4base8internal7InvokerINS0_9BindStateIMN5blink9scheduler16TaskQueueManagerEFvNS_9TimeTicksEbEJNS_7WeakPtrIS5_EES6_bEEEFvvEE3RunEPNS0_13BindStateBaseE
#34 0x7f2073913421 _ZNO4base8internal8RunMixinINS_8CallbackIFvvELNS0_8CopyModeE0ELNS0_10RepeatModeE0EEEE3RunEv
#35 0x7f2073912e29 base::debug::TaskAnnotator::RunTask()
#36 0x7f20739a592a base::MessageLoop::RunTask()
#37 0x7f20739a5bb4 base::MessageLoop::DeferOrRunPendingTask()
#38 0x7f20739a5e9e base::MessageLoop::DoWork()
#39 0x7f20739bd7f3 base::MessagePumpDefault::Run()
#40 0x7f20739a54aa base::MessageLoop::RunHandler()
#41 0x7f2073a4afe4 base::RunLoop::Run()
#42 0x7f2073af1518 base::Thread::Run()
#43 0x7f2073af1dba base::Thread::ThreadMain()
#44 0x7f2073ad8dda base::(anonymous namespace)::ThreadFunc()
#45 0x7f2073d4b184 start_thread
#46 0x7f2060d5137d clone

Ken Rockot

unread,
Oct 31, 2016, 1:56:56 PM10/31/16
to Makoto Shimazu, chromium-mojo
Apologies for the lack of documentation on proper Channel-associated interface usage. I'll fix this very soon.

You cannot use Channel-associated interfaces outside of the main thread or IO thread. Due to internal complexity which would result otherwise, we currently have no intention of supporting this use case.

If you need to send messages from arbitrary threads and you really need to use Channel-associated interfaces, you will have to have some state which lives on the IO thread and PostTask to/from it for send/receive.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-mojo+unsubscribe@chromium.org.
To post to this group, send email to chromi...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-mojo/CAHg_a%2BuV%2Bo%2BL7B_XC4%2Bn3Dw%2B8so455N%2BP3nmGKKMuH_yM8-Pkg%40mail.gmail.com.

Makoto Shimazu

unread,
Nov 1, 2016, 12:07:59 AM11/1/16
to Ken Rockot, chromium-mojo
Thanks, I see...
I'll try to consider whether I could use InterfacePtr somehow instead of the channel-associated interface. 

On Tue, Nov 1, 2016 at 2:56 AM Ken Rockot <roc...@chromium.org> wrote:
Apologies for the lack of documentation on proper Channel-associated interface usage. I'll fix this very soon.

You cannot use Channel-associated interfaces outside of the main thread or IO thread. Due to internal complexity which would result otherwise, we currently have no intention of supporting this use case.

If you need to send messages from arbitrary threads and you really need to use Channel-associated interfaces, you will have to have some state which lives on the IO thread and PostTask to/from it for send/receive.
 
Do you mean putting a channel-associated interface pointer on the IO thread and calling it via PostTask, for example?
 
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

To post to this group, send email to chromi...@chromium.org.

Makoto Shimazu

unread,
Nov 2, 2016, 5:26:41 AM11/2/16
to Makoto Shimazu, Ken Rockot, chromium-mojo
I have an additional question. Can I keep the ordering by just using PostTask to the IO thread and calling InterfacePtr there?
For example,

class MojoSender {
  MojoSender() {
    // set up |some_interface_| on the IO thread
  }
  void SendAnotherMessage() {
    some_interface_->AnotherMessage();
  }
  mojo::InterfacePtr<mojom::SomeInterface> some_interface_;
};

void IsTheseIPCsKeptOrdering() {
  thread_safe_sender_->Send(new SomeMessage());
  io_task_runner_->PostTask(
    base::Bind(&MojoSender::SendAnotherMessage, 
               base::Unretained(mojo_sender_)));
}

# I guess this might be what you said, right?

Ken Rockot

unread,
Nov 3, 2016, 6:21:43 PM11/3/16
to Makoto Shimazu, chromium-mojo
On Wed, Nov 2, 2016 at 2:26 AM, Makoto Shimazu <shi...@chromium.org> wrote:
I have an additional question. Can I keep the ordering by just using PostTask to the IO thread and calling InterfacePtr there?
For example,

class MojoSender {
  MojoSender() {
    // set up |some_interface_| on the IO thread
  }
  void SendAnotherMessage() {
    some_interface_->AnotherMessage();
  }
  mojo::InterfacePtr<mojom::SomeInterface> some_interface_;
};

void IsTheseIPCsKeptOrdering() {
  thread_safe_sender_->Send(new SomeMessage());
  io_task_runner_->PostTask(
    base::Bind(&MojoSender::SendAnotherMessage, 
               base::Unretained(mojo_sender_)));
}

# I guess this might be what you said, right?

This only works if it's an AssociatedInterfacePtr (for a Channel-associated interface).

InterfacePtr always has its own independent message pipe which makes no ordering guarantees with respect to any other pipe.
 

To unsubscribe from this group and stop receiving emails from it, send an email to chromium-mojo+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-mojo+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-mojo+unsubscribe@chromium.org.

To post to this group, send email to chromi...@chromium.org.

Makoto Shimazu

unread,
Nov 3, 2016, 9:12:25 PM11/3/16
to Ken Rockot, Makoto Shimazu, chromium-mojo
On Fri, Nov 4, 2016 at 7:21 AM Ken Rockot <roc...@chromium.org> wrote:
On Wed, Nov 2, 2016 at 2:26 AM, Makoto Shimazu <shi...@chromium.org> wrote:
I have an additional question. Can I keep the ordering by just using PostTask to the IO thread and calling InterfacePtr there?
For example,

class MojoSender {
  MojoSender() {
    // set up |some_interface_| on the IO thread
  }
  void SendAnotherMessage() {
    some_interface_->AnotherMessage();
  }
  mojo::InterfacePtr<mojom::SomeInterface> some_interface_;
};

void IsTheseIPCsKeptOrdering() {
  thread_safe_sender_->Send(new SomeMessage());
  io_task_runner_->PostTask(
    base::Bind(&MojoSender::SendAnotherMessage, 
               base::Unretained(mojo_sender_)));
}

# I guess this might be what you said, right?

This only works if it's an AssociatedInterfacePtr (for a Channel-associated interface).

InterfacePtr always has its own independent message pipe which makes no ordering guarantees with respect to any other pipe.

Got  it, thanks:)
 
 

To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

To post to this group, send email to chromi...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "chromium-mojo" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-moj...@chromium.org.

To post to this group, send email to chromi...@chromium.org.
Reply all
Reply to author
Forward
0 new messages