• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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