1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #ifndef IPC_IPC_SYNC_CHANNEL_H_
6*635a8641SAndroid Build Coastguard Worker #define IPC_IPC_SYNC_CHANNEL_H_
7*635a8641SAndroid Build Coastguard Worker
8*635a8641SAndroid Build Coastguard Worker #include <memory>
9*635a8641SAndroid Build Coastguard Worker #include <string>
10*635a8641SAndroid Build Coastguard Worker #include <vector>
11*635a8641SAndroid Build Coastguard Worker
12*635a8641SAndroid Build Coastguard Worker #include "base/component_export.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event_watcher.h"
18*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel_handle.h"
19*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel_proxy.h"
20*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_sync_message.h"
21*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_sync_message_filter.h"
22*635a8641SAndroid Build Coastguard Worker #include "mojo/public/c/system/types.h"
23*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/system/simple_watcher.h"
24*635a8641SAndroid Build Coastguard Worker
25*635a8641SAndroid Build Coastguard Worker namespace base {
26*635a8641SAndroid Build Coastguard Worker class RunLoop;
27*635a8641SAndroid Build Coastguard Worker class WaitableEvent;
28*635a8641SAndroid Build Coastguard Worker };
29*635a8641SAndroid Build Coastguard Worker
30*635a8641SAndroid Build Coastguard Worker namespace mojo {
31*635a8641SAndroid Build Coastguard Worker class SyncHandleRegistry;
32*635a8641SAndroid Build Coastguard Worker }
33*635a8641SAndroid Build Coastguard Worker
34*635a8641SAndroid Build Coastguard Worker namespace IPC {
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker class ChannelFactory;
37*635a8641SAndroid Build Coastguard Worker class SyncMessage;
38*635a8641SAndroid Build Coastguard Worker
39*635a8641SAndroid Build Coastguard Worker // This is similar to ChannelProxy, with the added feature of supporting sending
40*635a8641SAndroid Build Coastguard Worker // synchronous messages.
41*635a8641SAndroid Build Coastguard Worker //
42*635a8641SAndroid Build Coastguard Worker // Overview of how the sync channel works
43*635a8641SAndroid Build Coastguard Worker // --------------------------------------
44*635a8641SAndroid Build Coastguard Worker // When the sending thread sends a synchronous message, we create a bunch
45*635a8641SAndroid Build Coastguard Worker // of tracking info (created in Send, stored in the PendingSyncMsg
46*635a8641SAndroid Build Coastguard Worker // structure) associated with the message that we identify by the unique
47*635a8641SAndroid Build Coastguard Worker // "MessageId" on the SyncMessage. Among the things we save is the
48*635a8641SAndroid Build Coastguard Worker // "Deserializer" which is provided by the sync message. This object is in
49*635a8641SAndroid Build Coastguard Worker // charge of reading the parameters from the reply message and putting them in
50*635a8641SAndroid Build Coastguard Worker // the output variables provided by its caller.
51*635a8641SAndroid Build Coastguard Worker //
52*635a8641SAndroid Build Coastguard Worker // The info gets stashed in a queue since we could have a nested stack of sync
53*635a8641SAndroid Build Coastguard Worker // messages (each side could send sync messages in response to sync messages,
54*635a8641SAndroid Build Coastguard Worker // so it works like calling a function). The message is sent to the I/O thread
55*635a8641SAndroid Build Coastguard Worker // for dispatch and the original thread blocks waiting for the reply.
56*635a8641SAndroid Build Coastguard Worker //
57*635a8641SAndroid Build Coastguard Worker // SyncContext maintains the queue in a threadsafe way and listens for replies
58*635a8641SAndroid Build Coastguard Worker // on the I/O thread. When a reply comes in that matches one of the messages
59*635a8641SAndroid Build Coastguard Worker // it's looking for (using the unique message ID), it will execute the
60*635a8641SAndroid Build Coastguard Worker // deserializer stashed from before, and unblock the original thread.
61*635a8641SAndroid Build Coastguard Worker //
62*635a8641SAndroid Build Coastguard Worker //
63*635a8641SAndroid Build Coastguard Worker // Significant complexity results from the fact that messages are still coming
64*635a8641SAndroid Build Coastguard Worker // in while the original thread is blocked. Normal async messages are queued
65*635a8641SAndroid Build Coastguard Worker // and dispatched after the blocking call is complete. Sync messages must
66*635a8641SAndroid Build Coastguard Worker // be dispatched in a reentrant manner to avoid deadlock.
67*635a8641SAndroid Build Coastguard Worker //
68*635a8641SAndroid Build Coastguard Worker //
69*635a8641SAndroid Build Coastguard Worker // Note that care must be taken that the lifetime of the ipc_thread argument
70*635a8641SAndroid Build Coastguard Worker // is more than this object. If the message loop goes away while this object
71*635a8641SAndroid Build Coastguard Worker // is running and it's used to send a message, then it will use the invalid
72*635a8641SAndroid Build Coastguard Worker // message loop pointer to proxy it to the ipc thread.
COMPONENT_EXPORT(IPC)73*635a8641SAndroid Build Coastguard Worker class COMPONENT_EXPORT(IPC) SyncChannel : public ChannelProxy {
74*635a8641SAndroid Build Coastguard Worker public:
75*635a8641SAndroid Build Coastguard Worker enum RestrictDispatchGroup {
76*635a8641SAndroid Build Coastguard Worker kRestrictDispatchGroup_None = 0,
77*635a8641SAndroid Build Coastguard Worker };
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker // Creates and initializes a sync channel. If create_pipe_now is specified,
80*635a8641SAndroid Build Coastguard Worker // the channel will be initialized synchronously.
81*635a8641SAndroid Build Coastguard Worker // The naming pattern follows IPC::Channel.
82*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<SyncChannel> Create(
83*635a8641SAndroid Build Coastguard Worker const IPC::ChannelHandle& channel_handle,
84*635a8641SAndroid Build Coastguard Worker IPC::Channel::Mode mode,
85*635a8641SAndroid Build Coastguard Worker Listener* listener,
86*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
87*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
88*635a8641SAndroid Build Coastguard Worker bool create_pipe_now,
89*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event);
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<SyncChannel> Create(
92*635a8641SAndroid Build Coastguard Worker std::unique_ptr<ChannelFactory> factory,
93*635a8641SAndroid Build Coastguard Worker Listener* listener,
94*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
95*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
96*635a8641SAndroid Build Coastguard Worker bool create_pipe_now,
97*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event);
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard Worker // Creates an uninitialized sync channel. Call ChannelProxy::Init to
100*635a8641SAndroid Build Coastguard Worker // initialize the channel. This two-step setup allows message filters to be
101*635a8641SAndroid Build Coastguard Worker // added before any messages are sent or received.
102*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<SyncChannel> Create(
103*635a8641SAndroid Build Coastguard Worker Listener* listener,
104*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
105*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
106*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event);
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker ~SyncChannel() override;
109*635a8641SAndroid Build Coastguard Worker
110*635a8641SAndroid Build Coastguard Worker bool Send(Message* message) override;
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker // Sets the dispatch group for this channel, to only allow re-entrant dispatch
113*635a8641SAndroid Build Coastguard Worker // of messages to other channels in the same group.
114*635a8641SAndroid Build Coastguard Worker //
115*635a8641SAndroid Build Coastguard Worker // Normally, any unblocking message coming from any channel can be dispatched
116*635a8641SAndroid Build Coastguard Worker // when any (possibly other) channel is blocked on sending a message. This is
117*635a8641SAndroid Build Coastguard Worker // needed in some cases to unblock certain loops (e.g. necessary when some
118*635a8641SAndroid Build Coastguard Worker // processes share a window hierarchy), but may cause re-entrancy issues in
119*635a8641SAndroid Build Coastguard Worker // some cases where such loops are not possible. This flags allows the tagging
120*635a8641SAndroid Build Coastguard Worker // of some particular channels to only re-enter in known correct cases.
121*635a8641SAndroid Build Coastguard Worker //
122*635a8641SAndroid Build Coastguard Worker // Incoming messages on channels belonging to a group that is not
123*635a8641SAndroid Build Coastguard Worker // kRestrictDispatchGroup_None will only be dispatched while a sync message is
124*635a8641SAndroid Build Coastguard Worker // being sent on a channel of the *same* group.
125*635a8641SAndroid Build Coastguard Worker // Incoming messages belonging to the kRestrictDispatchGroup_None group (the
126*635a8641SAndroid Build Coastguard Worker // default) will be dispatched in any case.
127*635a8641SAndroid Build Coastguard Worker void SetRestrictDispatchChannelGroup(int group);
128*635a8641SAndroid Build Coastguard Worker
129*635a8641SAndroid Build Coastguard Worker // Creates a new IPC::SyncMessageFilter and adds it to this SyncChannel.
130*635a8641SAndroid Build Coastguard Worker // This should be used instead of directly constructing a new
131*635a8641SAndroid Build Coastguard Worker // SyncMessageFilter.
132*635a8641SAndroid Build Coastguard Worker scoped_refptr<IPC::SyncMessageFilter> CreateSyncMessageFilter();
133*635a8641SAndroid Build Coastguard Worker
134*635a8641SAndroid Build Coastguard Worker protected:
135*635a8641SAndroid Build Coastguard Worker class ReceivedSyncMsgQueue;
136*635a8641SAndroid Build Coastguard Worker friend class ReceivedSyncMsgQueue;
137*635a8641SAndroid Build Coastguard Worker
138*635a8641SAndroid Build Coastguard Worker // SyncContext holds the per object data for SyncChannel, so that SyncChannel
139*635a8641SAndroid Build Coastguard Worker // can be deleted while it's being used in a different thread. See
140*635a8641SAndroid Build Coastguard Worker // ChannelProxy::Context for more information.
141*635a8641SAndroid Build Coastguard Worker class SyncContext : public Context {
142*635a8641SAndroid Build Coastguard Worker public:
143*635a8641SAndroid Build Coastguard Worker SyncContext(
144*635a8641SAndroid Build Coastguard Worker Listener* listener,
145*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
146*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
147*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event);
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard Worker // Adds information about an outgoing sync message to the context so that
150*635a8641SAndroid Build Coastguard Worker // we know how to deserialize the reply.
151*635a8641SAndroid Build Coastguard Worker bool Push(SyncMessage* sync_msg);
152*635a8641SAndroid Build Coastguard Worker
153*635a8641SAndroid Build Coastguard Worker // Cleanly remove the top deserializer (and throw it away). Returns the
154*635a8641SAndroid Build Coastguard Worker // result of the Send call for that message.
155*635a8641SAndroid Build Coastguard Worker bool Pop();
156*635a8641SAndroid Build Coastguard Worker
157*635a8641SAndroid Build Coastguard Worker // Returns a Mojo Event that signals when a sync send is complete or timed
158*635a8641SAndroid Build Coastguard Worker // out or the process shut down.
159*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* GetSendDoneEvent();
160*635a8641SAndroid Build Coastguard Worker
161*635a8641SAndroid Build Coastguard Worker // Returns a Mojo Event that signals when an incoming message that's not the
162*635a8641SAndroid Build Coastguard Worker // pending reply needs to get dispatched (by calling DispatchMessages.)
163*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* GetDispatchEvent();
164*635a8641SAndroid Build Coastguard Worker
165*635a8641SAndroid Build Coastguard Worker void DispatchMessages();
166*635a8641SAndroid Build Coastguard Worker
167*635a8641SAndroid Build Coastguard Worker // Checks if the given message is blocking the listener thread because of a
168*635a8641SAndroid Build Coastguard Worker // synchronous send. If it is, the thread is unblocked and true is
169*635a8641SAndroid Build Coastguard Worker // returned. Otherwise the function returns false.
170*635a8641SAndroid Build Coastguard Worker bool TryToUnblockListener(const Message* msg);
171*635a8641SAndroid Build Coastguard Worker
172*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event() { return shutdown_event_; }
173*635a8641SAndroid Build Coastguard Worker
174*635a8641SAndroid Build Coastguard Worker ReceivedSyncMsgQueue* received_sync_msgs() {
175*635a8641SAndroid Build Coastguard Worker return received_sync_msgs_.get();
176*635a8641SAndroid Build Coastguard Worker }
177*635a8641SAndroid Build Coastguard Worker
178*635a8641SAndroid Build Coastguard Worker void set_restrict_dispatch_group(int group) {
179*635a8641SAndroid Build Coastguard Worker restrict_dispatch_group_ = group;
180*635a8641SAndroid Build Coastguard Worker }
181*635a8641SAndroid Build Coastguard Worker
182*635a8641SAndroid Build Coastguard Worker int restrict_dispatch_group() const {
183*635a8641SAndroid Build Coastguard Worker return restrict_dispatch_group_;
184*635a8641SAndroid Build Coastguard Worker }
185*635a8641SAndroid Build Coastguard Worker
186*635a8641SAndroid Build Coastguard Worker void OnSendDoneEventSignaled(base::RunLoop* nested_loop,
187*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* event);
188*635a8641SAndroid Build Coastguard Worker
189*635a8641SAndroid Build Coastguard Worker private:
190*635a8641SAndroid Build Coastguard Worker ~SyncContext() override;
191*635a8641SAndroid Build Coastguard Worker // ChannelProxy methods that we override.
192*635a8641SAndroid Build Coastguard Worker
193*635a8641SAndroid Build Coastguard Worker // Called on the listener thread.
194*635a8641SAndroid Build Coastguard Worker void Clear() override;
195*635a8641SAndroid Build Coastguard Worker
196*635a8641SAndroid Build Coastguard Worker // Called on the IPC thread.
197*635a8641SAndroid Build Coastguard Worker bool OnMessageReceived(const Message& msg) override;
198*635a8641SAndroid Build Coastguard Worker void OnChannelError() override;
199*635a8641SAndroid Build Coastguard Worker void OnChannelOpened() override;
200*635a8641SAndroid Build Coastguard Worker void OnChannelClosed() override;
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard Worker // Cancels all pending Send calls.
203*635a8641SAndroid Build Coastguard Worker void CancelPendingSends();
204*635a8641SAndroid Build Coastguard Worker
205*635a8641SAndroid Build Coastguard Worker void OnShutdownEventSignaled(base::WaitableEvent* event);
206*635a8641SAndroid Build Coastguard Worker
207*635a8641SAndroid Build Coastguard Worker using PendingSyncMessageQueue = base::circular_deque<PendingSyncMsg>;
208*635a8641SAndroid Build Coastguard Worker PendingSyncMessageQueue deserializers_;
209*635a8641SAndroid Build Coastguard Worker bool reject_new_deserializers_ = false;
210*635a8641SAndroid Build Coastguard Worker base::Lock deserializers_lock_;
211*635a8641SAndroid Build Coastguard Worker
212*635a8641SAndroid Build Coastguard Worker scoped_refptr<ReceivedSyncMsgQueue> received_sync_msgs_;
213*635a8641SAndroid Build Coastguard Worker
214*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event_;
215*635a8641SAndroid Build Coastguard Worker base::WaitableEventWatcher shutdown_watcher_;
216*635a8641SAndroid Build Coastguard Worker base::WaitableEventWatcher::EventCallback shutdown_watcher_callback_;
217*635a8641SAndroid Build Coastguard Worker int restrict_dispatch_group_;
218*635a8641SAndroid Build Coastguard Worker };
219*635a8641SAndroid Build Coastguard Worker
220*635a8641SAndroid Build Coastguard Worker private:
221*635a8641SAndroid Build Coastguard Worker SyncChannel(
222*635a8641SAndroid Build Coastguard Worker Listener* listener,
223*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
224*635a8641SAndroid Build Coastguard Worker const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner,
225*635a8641SAndroid Build Coastguard Worker base::WaitableEvent* shutdown_event);
226*635a8641SAndroid Build Coastguard Worker
227*635a8641SAndroid Build Coastguard Worker void OnDispatchEventSignaled(base::WaitableEvent* event);
228*635a8641SAndroid Build Coastguard Worker
229*635a8641SAndroid Build Coastguard Worker SyncContext* sync_context() {
230*635a8641SAndroid Build Coastguard Worker return reinterpret_cast<SyncContext*>(context());
231*635a8641SAndroid Build Coastguard Worker }
232*635a8641SAndroid Build Coastguard Worker
233*635a8641SAndroid Build Coastguard Worker // Both these functions wait for a reply, timeout or process shutdown. The
234*635a8641SAndroid Build Coastguard Worker // latter one also runs a nested run loop in the meantime.
235*635a8641SAndroid Build Coastguard Worker static void WaitForReply(mojo::SyncHandleRegistry* registry,
236*635a8641SAndroid Build Coastguard Worker SyncContext* context,
237*635a8641SAndroid Build Coastguard Worker bool pump_messages);
238*635a8641SAndroid Build Coastguard Worker
239*635a8641SAndroid Build Coastguard Worker // Runs a nested run loop until a reply arrives, times out, or the process
240*635a8641SAndroid Build Coastguard Worker // shuts down.
241*635a8641SAndroid Build Coastguard Worker static void WaitForReplyWithNestedMessageLoop(SyncContext* context);
242*635a8641SAndroid Build Coastguard Worker
243*635a8641SAndroid Build Coastguard Worker // Starts the dispatch watcher.
244*635a8641SAndroid Build Coastguard Worker void StartWatching();
245*635a8641SAndroid Build Coastguard Worker
246*635a8641SAndroid Build Coastguard Worker // ChannelProxy overrides:
247*635a8641SAndroid Build Coastguard Worker void OnChannelInit() override;
248*635a8641SAndroid Build Coastguard Worker
249*635a8641SAndroid Build Coastguard Worker scoped_refptr<mojo::SyncHandleRegistry> sync_handle_registry_;
250*635a8641SAndroid Build Coastguard Worker
251*635a8641SAndroid Build Coastguard Worker // Used to signal events between the IPC and listener threads.
252*635a8641SAndroid Build Coastguard Worker base::WaitableEventWatcher dispatch_watcher_;
253*635a8641SAndroid Build Coastguard Worker base::WaitableEventWatcher::EventCallback dispatch_watcher_callback_;
254*635a8641SAndroid Build Coastguard Worker
255*635a8641SAndroid Build Coastguard Worker // Tracks SyncMessageFilters created before complete channel initialization.
256*635a8641SAndroid Build Coastguard Worker std::vector<scoped_refptr<SyncMessageFilter>> pre_init_sync_message_filters_;
257*635a8641SAndroid Build Coastguard Worker
258*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SyncChannel);
259*635a8641SAndroid Build Coastguard Worker };
260*635a8641SAndroid Build Coastguard Worker
261*635a8641SAndroid Build Coastguard Worker } // namespace IPC
262*635a8641SAndroid Build Coastguard Worker
263*635a8641SAndroid Build Coastguard Worker #endif // IPC_IPC_SYNC_CHANNEL_H_
264