[UNIX] Simplify the file descriptor handling in SharedMemory
[WebKit-https.git] / Source / WebKit2 / Platform / IPC / Connection.h
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef Connection_h
29 #define Connection_h
30
31 #include "Arguments.h"
32 #include "MessageDecoder.h"
33 #include "MessageEncoder.h"
34 #include "MessageReceiver.h"
35 #include "ProcessType.h"
36 #include <atomic>
37 #include <condition_variable>
38 #include <wtf/Deque.h>
39 #include <wtf/Forward.h>
40 #include <wtf/HashMap.h>
41 #include <wtf/WorkQueue.h>
42 #include <wtf/text/CString.h>
43
44 #if OS(DARWIN)
45 #include <mach/mach_port.h>
46 #include <wtf/OSObjectPtr.h>
47 #include <wtf/spi/darwin/XPCSPI.h>
48 #endif
49
50 #if PLATFORM(GTK) || PLATFORM(EFL)
51 #include "PlatformProcessIdentifier.h"
52 #endif
53
54 namespace WTF {
55 class RunLoop;
56 }
57
58 namespace IPC {
59
60 struct WaitForMessageState;
61
62 enum MessageSendFlags {
63     // Whether this message should be dispatched when waiting for a sync reply.
64     // This is the default for synchronous messages.
65     DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
66 };
67
68 enum SyncMessageSendFlags {
69     // Use this to inform that this sync call will suspend this process until the user responds with input.
70     InformPlatformProcessWillSuspend = 1 << 0,
71     // Some platform accessibility clients can't suspend gracefully and need to spin the run loop so WebProcess doesn't hang.
72     // FIXME (126021): Remove when no platforms need to support this.
73     SpinRunLoopWhileWaitingForReply = 1 << 1,
74 };
75
76 enum WaitForMessageFlags {
77     // Use this to make waitForMessage be interrupted immediately by any incoming sync messages.
78     InterruptWaitingIfSyncMessageArrives = 1 << 0,
79 };
80
81 #define MESSAGE_CHECK_BASE(assertion, connection) do \
82     if (!(assertion)) { \
83         ASSERT(assertion); \
84         (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
85         return; \
86     } \
87 while (0)
88
89 class Connection : public ThreadSafeRefCounted<Connection> {
90 public:
91     class Client : public MessageReceiver {
92     public:
93         virtual void didClose(Connection&) = 0;
94         virtual void didReceiveInvalidMessage(Connection&, StringReference messageReceiverName, StringReference messageName) = 0;
95         virtual IPC::ProcessType localProcessType() = 0;
96         virtual IPC::ProcessType remoteProcessType() = 0;
97
98     protected:
99         virtual ~Client() { }
100     };
101
102     class WorkQueueMessageReceiver : public MessageReceiver, public ThreadSafeRefCounted<WorkQueueMessageReceiver> {
103     };
104
105 #if OS(DARWIN)
106     struct Identifier {
107         Identifier()
108             : port(MACH_PORT_NULL)
109         {
110         }
111
112         Identifier(mach_port_t port)
113             : port(port)
114         {
115         }
116
117         Identifier(mach_port_t port, OSObjectPtr<xpc_connection_t> xpcConnection)
118             : port(port)
119             , xpcConnection(WTF::move(xpcConnection))
120         {
121         }
122
123         mach_port_t port;
124         OSObjectPtr<xpc_connection_t> xpcConnection;
125     };
126     static bool identifierIsNull(Identifier identifier) { return identifier.port == MACH_PORT_NULL; }
127     xpc_connection_t xpcConnection() const { return m_xpcConnection.get(); }
128     bool getAuditToken(audit_token_t&);
129     pid_t remoteProcessID() const;
130 #elif USE(UNIX_DOMAIN_SOCKETS)
131     typedef int Identifier;
132     static bool identifierIsNull(Identifier identifier) { return identifier == -1; }
133
134     struct SocketPair {
135         int client;
136         int server;
137     };
138
139     enum ConnectionOptions {
140         SetCloexecOnClient = 1 << 0,
141         SetCloexecOnServer = 1 << 1,
142     };
143
144     static Connection::SocketPair createPlatformConnection(unsigned options = SetCloexecOnClient | SetCloexecOnServer);
145 #endif
146
147     static Ref<Connection> createServerConnection(Identifier, Client&, WTF::RunLoop& clientRunLoop);
148     static Ref<Connection> createClientConnection(Identifier, Client&, WTF::RunLoop& clientRunLoop);
149     ~Connection();
150
151     Client* client() const { return m_client; }
152
153 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
154     void setShouldCloseConnectionOnMachExceptions();
155 #endif
156
157     void setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(bool);
158     void setShouldExitOnSyncMessageSendFailure(bool shouldExitOnSyncMessageSendFailure);
159
160     // The set callback will be called on the connection work queue when the connection is closed, 
161     // before didCall is called on the client thread. Must be called before the connection is opened.
162     // In the future we might want a more generic way to handle sync or async messages directly
163     // on the work queue, for example if we want to handle them on some other thread we could avoid
164     // handling the message on the client thread first.
165     typedef void (*DidCloseOnConnectionWorkQueueCallback)(Connection*);
166     void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
167
168     void addWorkQueueMessageReceiver(StringReference messageReceiverName, WorkQueue*, WorkQueueMessageReceiver*);
169     void removeWorkQueueMessageReceiver(StringReference messageReceiverName);
170
171     bool open();
172     void invalidate();
173     void markCurrentlyDispatchedMessageAsInvalid();
174
175     void postConnectionDidCloseOnConnectionWorkQueue();
176
177     template<typename T> bool send(T&& message, uint64_t destinationID, unsigned messageSendFlags = 0);
178     template<typename T> bool sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout = std::chrono::milliseconds::max(), unsigned syncSendFlags = 0);
179     template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags = 0);
180
181     std::unique_ptr<MessageEncoder> createSyncMessageEncoder(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, uint64_t& syncRequestID);
182     bool sendMessage(std::unique_ptr<MessageEncoder>, unsigned messageSendFlags = 0, bool alreadyRecordedMessage = false);
183     std::unique_ptr<MessageDecoder> sendSyncMessage(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout, unsigned syncSendFlags = 0);
184     std::unique_ptr<MessageDecoder> sendSyncMessageFromSecondaryThread(uint64_t syncRequestID, std::unique_ptr<MessageEncoder>, std::chrono::milliseconds timeout);
185     bool sendSyncReply(std::unique_ptr<MessageEncoder>);
186
187     void wakeUpRunLoop();
188
189     void incrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { ++m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
190     void decrementDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount() { --m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount; }
191
192     bool inSendSync() const { return m_inSendSyncCount; }
193
194     Identifier identifier() const;
195
196 #if PLATFORM(COCOA)
197     bool kill();
198     void terminateSoon(double intervalInSeconds);
199 #endif
200
201     bool isValid() const { return m_client; }
202
203 #if HAVE(QOS_CLASSES)
204     void setShouldBoostMainThreadOnSyncMessage(bool b) { m_shouldBoostMainThreadOnSyncMessage = b; }
205 #endif
206
207 private:
208     Connection(Identifier, bool isServer, Client&, WTF::RunLoop& clientRunLoop);
209     void platformInitialize(Identifier);
210     void platformInvalidate();
211     
212     std::unique_ptr<MessageDecoder> waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags);
213     
214     std::unique_ptr<MessageDecoder> waitForSyncReply(uint64_t syncRequestID, std::chrono::milliseconds timeout, unsigned syncSendFlags);
215
216     // Called on the connection work queue.
217     void processIncomingMessage(std::unique_ptr<MessageDecoder>);
218     void processIncomingSyncReply(std::unique_ptr<MessageDecoder>);
219
220     void dispatchWorkQueueMessageReceiverMessage(WorkQueueMessageReceiver&, MessageDecoder&);
221
222     bool canSendOutgoingMessages() const;
223     bool platformCanSendOutgoingMessages() const;
224     void sendOutgoingMessages();
225     bool sendOutgoingMessage(std::unique_ptr<MessageEncoder>);
226     void connectionDidClose();
227     
228     // Called on the listener thread.
229     void dispatchOneMessage();
230     void dispatchMessage(std::unique_ptr<MessageDecoder>);
231     void dispatchMessage(MessageDecoder&);
232     void dispatchSyncMessage(MessageDecoder&);
233     void dispatchDidReceiveInvalidMessage(const CString& messageReceiverNameString, const CString& messageNameString);
234     void didFailToSendSyncMessage();
235
236     // Can be called on any thread.
237     void enqueueIncomingMessage(std::unique_ptr<MessageDecoder>);
238
239     void willSendSyncMessage(unsigned syncSendFlags);
240     void didReceiveSyncReply(unsigned syncSendFlags);
241     
242     Client* m_client;
243     bool m_isServer;
244     std::atomic<uint64_t> m_syncRequestID;
245
246     bool m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage;
247     bool m_shouldExitOnSyncMessageSendFailure;
248     DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
249
250     bool m_isConnected;
251     Ref<WorkQueue> m_connectionQueue;
252     WTF::RunLoop& m_clientRunLoop;
253
254     HashMap<StringReference, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>> m_workQueueMessageReceivers;
255
256     unsigned m_inSendSyncCount;
257     unsigned m_inDispatchMessageCount;
258     unsigned m_inDispatchMessageMarkedDispatchWhenWaitingForSyncReplyCount;
259     bool m_didReceiveInvalidMessage;
260
261     // Incoming messages.
262     std::mutex m_incomingMessagesMutex;
263     Deque<std::unique_ptr<MessageDecoder>> m_incomingMessages;
264
265     // Outgoing messages.
266     std::mutex m_outgoingMessagesMutex;
267     Deque<std::unique_ptr<MessageEncoder>> m_outgoingMessages;
268     
269     std::condition_variable m_waitForMessageCondition;
270     std::mutex m_waitForMessageMutex;
271
272     WaitForMessageState* m_waitingForMessage;
273
274     // Represents a sync request for which we're waiting on a reply.
275     struct PendingSyncReply {
276         // The request ID.
277         uint64_t syncRequestID;
278
279         // The reply decoder, will be null if there was an error processing the sync
280         // message on the other side.
281         std::unique_ptr<MessageDecoder> replyDecoder;
282
283         // Will be set to true once a reply has been received.
284         bool didReceiveReply;
285     
286         PendingSyncReply()
287             : syncRequestID(0)
288             , didReceiveReply(false)
289         {
290         }
291
292         explicit PendingSyncReply(uint64_t syncRequestID)
293             : syncRequestID(syncRequestID)
294             , didReceiveReply(0)
295         {
296         }
297     };
298
299     class SyncMessageState;
300     friend class SyncMessageState;
301     RefPtr<SyncMessageState> m_syncMessageState;
302
303     Mutex m_syncReplyStateMutex;
304     bool m_shouldWaitForSyncReplies;
305     Vector<PendingSyncReply> m_pendingSyncReplies;
306
307     class SecondaryThreadPendingSyncReply;
308     typedef HashMap<uint64_t, SecondaryThreadPendingSyncReply*> SecondaryThreadPendingSyncReplyMap;
309     SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap;
310
311 #if HAVE(QOS_CLASSES)
312     pthread_t m_mainThread { 0 };
313     bool m_shouldBoostMainThreadOnSyncMessage { false };
314 #endif
315
316 #if OS(DARWIN)
317     // Called on the connection queue.
318     void receiveSourceEventHandler();
319     void initializeDeadNameSource();
320
321     mach_port_t m_sendPort;
322     dispatch_source_t m_deadNameSource;
323
324     mach_port_t m_receivePort;
325     dispatch_source_t m_receivePortDataAvailableSource;
326
327 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000
328     void exceptionSourceEventHandler();
329
330     // If setShouldCloseConnectionOnMachExceptions has been called, this has
331     // the exception port that exceptions from the other end will be sent on.
332     mach_port_t m_exceptionPort;
333     dispatch_source_t m_exceptionPortDataAvailableSource;
334 #endif
335
336     OSObjectPtr<xpc_connection_t> m_xpcConnection;
337
338 #elif USE(UNIX_DOMAIN_SOCKETS)
339     // Called on the connection queue.
340     void readyReadHandler();
341     bool processMessage();
342
343     Vector<uint8_t> m_readBuffer;
344     size_t m_readBufferSize;
345     Vector<int> m_fileDescriptors;
346     size_t m_fileDescriptorsSize;
347     int m_socketDescriptor;
348 #endif
349 };
350
351 template<typename T> bool Connection::send(T&& message, uint64_t destinationID, unsigned messageSendFlags)
352 {
353     COMPILE_ASSERT(!T::isSync, AsyncMessageExpected);
354
355     auto encoder = std::make_unique<MessageEncoder>(T::receiverName(), T::name(), destinationID);
356     encoder->encode(message.arguments());
357     
358     return sendMessage(WTF::move(encoder), messageSendFlags);
359 }
360
361 template<typename T> bool Connection::sendSync(T&& message, typename T::Reply&& reply, uint64_t destinationID, std::chrono::milliseconds timeout, unsigned syncSendFlags)
362 {
363     COMPILE_ASSERT(T::isSync, SyncMessageExpected);
364
365     uint64_t syncRequestID = 0;
366     std::unique_ptr<MessageEncoder> encoder = createSyncMessageEncoder(T::receiverName(), T::name(), destinationID, syncRequestID);
367     
368     // Encode the rest of the input arguments.
369     encoder->encode(message.arguments());
370
371     // Now send the message and wait for a reply.
372     std::unique_ptr<MessageDecoder> replyDecoder = sendSyncMessage(syncRequestID, WTF::move(encoder), timeout, syncSendFlags);
373     if (!replyDecoder)
374         return false;
375
376     // Decode the reply.
377     return replyDecoder->decode(reply);
378 }
379
380 template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, std::chrono::milliseconds timeout, unsigned waitForMessageFlags)
381 {
382     std::unique_ptr<MessageDecoder> decoder = waitForMessage(T::receiverName(), T::name(), destinationID, timeout, waitForMessageFlags);
383     if (!decoder)
384         return false;
385
386     ASSERT(decoder->destinationID() == destinationID);
387     m_client->didReceiveMessage(*this, *decoder);
388     return true;
389 }
390
391 } // namespace IPC
392
393 #endif // Connection_h