1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_ 6 #define REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_ 7 8 #include "base/basictypes.h" 9 #include "base/callback.h" 10 #include "base/compiler_specific.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/threading/non_thread_safe.h" 14 #include "base/timer/timer.h" 15 #include "base/win/object_watcher.h" 16 #include "base/win/scoped_handle.h" 17 #include "net/base/backoff_entry.h" 18 19 namespace base { 20 class SingleThreadTaskRunner; 21 class TimeDelta; 22 } // namespace base 23 24 namespace IPC { 25 class Message; 26 } // namespace IPC 27 28 namespace tracked_objects { 29 class Location; 30 } // namespace tracked_objects 31 32 namespace remoting { 33 34 class WorkerProcessIpcDelegate; 35 36 // Launches a worker process that is controlled via an IPC channel. All 37 // interaction with the spawned process is through WorkerProcessIpcDelegate and 38 // Send() method. In case of error the channel is closed and the worker process 39 // is terminated. 40 class WorkerProcessLauncher 41 : public base::NonThreadSafe, 42 public base::win::ObjectWatcher::Delegate { 43 public: 44 class Delegate { 45 public: 46 virtual ~Delegate(); 47 48 // Asynchronously starts the worker process and creates an IPC channel it 49 // can connect to. |event_handler| must remain valid until KillProcess() has 50 // been called. 51 virtual void LaunchProcess(WorkerProcessLauncher* event_handler) = 0; 52 53 // Sends an IPC message to the worker process. The message will be silently 54 // dropped if the channel is closed. 55 virtual void Send(IPC::Message* message) = 0; 56 57 // Closes the IPC channel. 58 virtual void CloseChannel() = 0; 59 60 // Terminates the worker process and closes the IPC channel. 61 virtual void KillProcess() = 0; 62 }; 63 64 // Creates the launcher that will use |launcher_delegate| to manage the worker 65 // process and |ipc_handler| to handle IPCs. The caller must ensure that 66 // |ipc_handler| must outlive this object. 67 WorkerProcessLauncher(scoped_ptr<Delegate> launcher_delegate, 68 WorkerProcessIpcDelegate* ipc_handler); 69 virtual ~WorkerProcessLauncher(); 70 71 // Asks the worker process to crash and generate a dump, and closes the IPC 72 // channel. |location| is passed to the worker so that it is on the stack in 73 // the dump. Restarts the worker process forcefully, if it does 74 // not exit on its own. 75 void Crash(const tracked_objects::Location& location); 76 77 // Sends an IPC message to the worker process. The message will be silently 78 // dropped if Send() is called before Start() or after stutdown has been 79 // initiated. 80 void Send(IPC::Message* message); 81 82 // Notification methods invoked by |Delegate|. 83 84 // Invoked to pass a handle of the launched process back to the caller of 85 // Delegate::LaunchProcess(). The delegate has to make sure that this method 86 // is called before OnChannelConnected(). 87 void OnProcessLaunched(base::win::ScopedHandle worker_process); 88 89 // Called when a fatal error occurs (i.e. a failed process launch). 90 // The delegate must guarantee that no other notifications are delivered once 91 // OnFatalError() has been called. 92 void OnFatalError(); 93 94 // Mirrors methods of IPC::Listener to be invoked by |Delegate|. |Delegate| 95 // has to validate |peer_pid| if necessary. 96 bool OnMessageReceived(const IPC::Message& message); 97 void OnChannelConnected(int32 peer_pid); 98 void OnChannelError(); 99 100 private: 101 friend class WorkerProcessLauncherTest; 102 103 // base::win::ObjectWatcher::Delegate implementation used to watch for 104 // the worker process exiting. 105 virtual void OnObjectSignaled(HANDLE object) OVERRIDE; 106 107 // Returns true when the object is being destroyed. stopping()108 bool stopping() const { return ipc_handler_ == NULL; } 109 110 // Attempts to launch the worker process. Schedules next launch attempt if 111 // creation of the process fails. 112 void LaunchWorker(); 113 114 // Called to record outcome of a launch attempt: success or failure. 115 void RecordLaunchResult(); 116 117 // Called by the test to record a successful launch attempt. 118 void RecordSuccessfulLaunchForTest(); 119 120 // Set the desired timeout for |kill_process_timer_|. 121 void SetKillProcessTimeoutForTest(const base::TimeDelta& timeout); 122 123 // Stops the worker process and schedules next launch attempt unless the 124 // object is being destroyed already. 125 void StopWorker(); 126 127 // Handles IPC messages sent by the worker process. 128 WorkerProcessIpcDelegate* ipc_handler_; 129 130 // Implements specifics of launching a worker process. 131 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_; 132 133 // Keeps the exit code of the worker process after it was closed. The exit 134 // code is used to determine whether the process has to be restarted. 135 DWORD exit_code_; 136 137 // True if IPC messages should be passed to |ipc_handler_|. 138 bool ipc_enabled_; 139 140 // The timer used to delay termination of the worker process when an IPC error 141 // occured or when Crash() request is pending 142 base::OneShotTimer<WorkerProcessLauncher> kill_process_timer_; 143 144 // The default timeout for |kill_process_timer_|. 145 base::TimeDelta kill_process_timeout_; 146 147 // State used to backoff worker launch attempts on failure. 148 net::BackoffEntry launch_backoff_; 149 150 // Timer used to schedule the next attempt to launch the process. 151 base::OneShotTimer<WorkerProcessLauncher> launch_timer_; 152 153 // Monitors |worker_process_| to detect when the launched process 154 // terminates. 155 base::win::ObjectWatcher process_watcher_; 156 157 // Timer used to detect whether a launch attempt was successful or not, and to 158 // cancel the launch attempt if it is taking too long. 159 base::OneShotTimer<WorkerProcessLauncher> launch_result_timer_; 160 161 // The handle of the worker process, if launched. 162 base::win::ScopedHandle worker_process_; 163 164 DISALLOW_COPY_AND_ASSIGN(WorkerProcessLauncher); 165 }; 166 167 } // namespace remoting 168 169 #endif // REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_ 170