OLD | NEW |
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 #ifndef MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ | 5 #ifndef MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ |
6 #define MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ | 6 #define MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ |
7 | 7 |
8 #include "base/macros.h" | |
9 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
10 #include "base/task_runner.h" | |
11 #include "mojo/edk/system/system_impl_export.h" | 9 #include "mojo/edk/system/system_impl_export.h" |
12 | 10 |
| 11 namespace base { |
| 12 class TaskRunner; |
| 13 } |
| 14 |
13 namespace mojo { | 15 namespace mojo { |
14 namespace edk { | 16 namespace edk { |
15 | 17 |
16 // Performs any necessary Mojo initialization on construction, and shuts | 18 // A simple class that calls |InitIPCSupport()| on construction and |
17 // down Mojo on destruction. | 19 // |ShutdownIPCSupport()| on destruction, blocking the destructor on clean IPC |
18 // | 20 // shutdown completion. |
19 // This should be instantiated once per process and retained as long as Mojo | |
20 // is needed. The TaskRunner passed to the constructor should outlive this | |
21 // object. | |
22 class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport { | 21 class MOJO_SYSTEM_IMPL_EXPORT ScopedIPCSupport { |
23 public: | 22 public: |
24 ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner); | 23 // ShutdownPolicy is a type for specifying the desired Mojo IPC support |
| 24 // shutdown behavior used during ScopedIPCSupport destruction. |
| 25 // |
| 26 // What follows is a quick overview of why shutdown behavior is interesting |
| 27 // and how you might decide which behavior is right for your use case. |
| 28 // |
| 29 // BACKGROUND |
| 30 // ========== |
| 31 // |
| 32 // In order to facilitate efficient and reliable transfer of Mojo message pipe |
| 33 // endpoints across process boundaries, the underlying model for a message |
| 34 // pipe is actually a self-collapsing cycle of "ports." See |
| 35 // //mojo/edk/system/ports for gritty implementation details. |
| 36 // |
| 37 // Ports are essentially globally unique identifiers used for system-wide |
| 38 // message routing. Every message pipe consists of at least two such ports: |
| 39 // the pipe's two concrete endpoints. |
| 40 // |
| 41 // When a message pipe endpoint is transferred over another message pipe, that |
| 42 // endpoint's port (which subsequently exists only internally with no |
| 43 // publicly-reachable handle) enters a transient proxying state for the |
| 44 // remainder of its lifetime. Once sufficient information has been |
| 45 // proagated throughout the system and this proxying port can be safely |
| 46 // bypassed, it is garbage-collected. |
| 47 // |
| 48 // If a process is terminated while hosting any active proxy ports, this |
| 49 // will necessarily break the message pipe(s) to which those ports belong. |
| 50 // |
| 51 // WHEN TO USE CLEAN SHUTDOWN |
| 52 // ========================== |
| 53 // |
| 54 // Consider three processes, A, B, and C. Suppose A creates a message pipe, |
| 55 // sending one end to B and the other to C. For some brief period of time, |
| 56 // messages sent by B or C over this pipe may be proxied through A. |
| 57 // |
| 58 // If A is suddenly terminated, there may be no way for B's messages to reach |
| 59 // C (and vice versa), since the message pipe state may not have been fully |
| 60 // propagated to all concerned processes in the system. As such, both B and C |
| 61 // may have no choice but to signal peer closure on their respective ends of |
| 62 // the pipe, and thus the pipe may be broken despite a lack of intent by |
| 63 // either B or C. |
| 64 // |
| 65 // This can also happen if A creates a pipe and passes one end to B, who then |
| 66 // passes it along to C. B may temporarily proxy messages for this pipe |
| 67 // between A and C, and B's sudden demise will in turn beget the pipe's |
| 68 // own sudden demise. |
| 69 // |
| 70 // In situations where these sort of arrangements may occur, potentially |
| 71 // proxying processes must ensure they are shut down cleanly in order to avoid |
| 72 // flaky system behavior. |
| 73 // |
| 74 // WHEN TO USE FAST SHUTDOWN |
| 75 // ========================= |
| 76 // |
| 77 // As a general rule of thumb, if your process never creates a message pipe |
| 78 // where both ends are passed to other processes, or never forwards a pipe |
| 79 // endpoint from one process to another, fast shutdown is safe. Satisfaction |
| 80 // of these constraints can be difficult to prove though, so clean shutdown is |
| 81 // a safe default choice. |
| 82 // |
| 83 // Content renderer processes are a good example of a case where fast shutdown |
| 84 // is safe, because as a matter of security and stability, a renderer cannot |
| 85 // be trusted to do any proxying on behalf of two other processes anyway. |
| 86 // |
| 87 // There are other practical scenarios where fast shutdown is safe even if |
| 88 // the process may have live proxies. For example, content's browser process |
| 89 // is treated as a sort of master process in the system, in the sense that if |
| 90 // the browser is terminated, no other part of the system is expected to |
| 91 // continue normal operation anyway. In this case the side-effects of fast |
| 92 // shutdown are irrelevant, so fast shutdown is preferred. |
| 93 enum class ShutdownPolicy { |
| 94 // Clean shutdown. This causes the ScopedIPCSupport destructor to *block* |
| 95 // the calling thread until clean shutdown is complete. See explanation |
| 96 // above for details. |
| 97 CLEAN, |
| 98 |
| 99 // Fast shutdown. In this case a cheap best-effort attempt is made to |
| 100 // shut down the IPC system, but no effort is made to wait for its |
| 101 // completion. See explanation above for details. |
| 102 FAST, |
| 103 }; |
| 104 |
| 105 ScopedIPCSupport(scoped_refptr<base::TaskRunner> io_thread_task_runner, |
| 106 ShutdownPolicy shutdown_policy); |
25 ~ScopedIPCSupport(); | 107 ~ScopedIPCSupport(); |
26 | 108 |
27 private: | 109 private: |
| 110 const ShutdownPolicy shutdown_policy_; |
| 111 |
28 DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); | 112 DISALLOW_COPY_AND_ASSIGN(ScopedIPCSupport); |
29 }; | 113 }; |
30 | 114 |
31 } // namespace edk | 115 } // namespace edk |
32 } // namespace mojo | 116 } // namespace mojo |
33 | 117 |
34 #endif // MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ | 118 #endif // MOJO_EDK_EMBEDDER_SCOPED_IPC_SUPPORT_H_ |
OLD | NEW |