summaryrefslogtreecommitdiffstats
path: root/remoting/host/win/worker_process_launcher.h
blob: e263509e5ceab81f51d88b724850c47e8082522b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_
#define REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_

#include <stdint.h>

#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/timer/timer.h"
#include "base/win/object_watcher.h"
#include "base/win/scoped_handle.h"
#include "net/base/backoff_entry.h"

namespace base {
class SingleThreadTaskRunner;
class TimeDelta;
} // namespace base

namespace IPC {
class Message;
} // namespace IPC

namespace tracked_objects {
class Location;
}  // namespace tracked_objects

namespace remoting {

class WorkerProcessIpcDelegate;

// Launches a worker process that is controlled via an IPC channel. All
// interaction with the spawned process is through WorkerProcessIpcDelegate and
// Send() method. In case of error the channel is closed and the worker process
// is terminated.
class WorkerProcessLauncher
    : public base::NonThreadSafe,
      public base::win::ObjectWatcher::Delegate {
 public:
  class Delegate {
   public:
    virtual ~Delegate();

    // Asynchronously starts the worker process and creates an IPC channel it
    // can connect to. |event_handler| must remain valid until KillProcess() has
    // been called.
    virtual void LaunchProcess(WorkerProcessLauncher* event_handler) = 0;

    // Sends an IPC message to the worker process. The message will be silently
    // dropped if the channel is closed.
    virtual void Send(IPC::Message* message) = 0;

    // Closes the IPC channel.
    virtual void CloseChannel() = 0;

    // Terminates the worker process and closes the IPC channel.
    virtual void KillProcess() = 0;
  };

  // Creates the launcher that will use |launcher_delegate| to manage the worker
  // process and |ipc_handler| to handle IPCs. The caller must ensure that
  // |ipc_handler| must outlive this object.
  WorkerProcessLauncher(scoped_ptr<Delegate> launcher_delegate,
                        WorkerProcessIpcDelegate* ipc_handler);
  ~WorkerProcessLauncher() override;

  // Asks the worker process to crash and generate a dump, and closes the IPC
  // channel. |location| is passed to the worker so that it is on the stack in
  // the dump. Restarts the worker process forcefully, if it does
  // not exit on its own.
  void Crash(const tracked_objects::Location& location);

  // Sends an IPC message to the worker process. The message will be silently
  // dropped if Send() is called before Start() or after stutdown has been
  // initiated.
  void Send(IPC::Message* message);

  // Notification methods invoked by |Delegate|.

  // Invoked to pass a handle of the launched process back to the caller of
  // Delegate::LaunchProcess(). The delegate has to make sure that this method
  // is called before OnChannelConnected().
  void OnProcessLaunched(base::win::ScopedHandle worker_process);

  // Called when a fatal error occurs (i.e. a failed process launch).
  // The delegate must guarantee that no other notifications are delivered once
  // OnFatalError() has been called.
  void OnFatalError();

  // Mirrors methods of IPC::Listener to be invoked by |Delegate|. |Delegate|
  // has to validate |peer_pid| if necessary.
  bool OnMessageReceived(const IPC::Message& message);
  void OnChannelConnected(int32_t peer_pid);
  void OnChannelError();

 private:
  friend class WorkerProcessLauncherTest;

  // base::win::ObjectWatcher::Delegate implementation used to watch for
  // the worker process exiting.
  void OnObjectSignaled(HANDLE object) override;

  // Returns true when the object is being destroyed.
  bool stopping() const { return ipc_handler_ == nullptr; }

  // Attempts to launch the worker process. Schedules next launch attempt if
  // creation of the process fails.
  void LaunchWorker();

  // Called to record outcome of a launch attempt: success or failure.
  void RecordLaunchResult();

  // Called by the test to record a successful launch attempt.
  void RecordSuccessfulLaunchForTest();

  // Set the desired timeout for |kill_process_timer_|.
  void SetKillProcessTimeoutForTest(const base::TimeDelta& timeout);

  // Stops the worker process and schedules next launch attempt unless the
  // object is being destroyed already.
  void StopWorker();

  // Handles IPC messages sent by the worker process.
  WorkerProcessIpcDelegate* ipc_handler_;

  // Implements specifics of launching a worker process.
  scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_;

  // Keeps the exit code of the worker process after it was closed. The exit
  // code is used to determine whether the process has to be restarted.
  DWORD exit_code_;

  // True if IPC messages should be passed to |ipc_handler_|.
  bool ipc_enabled_;

  // The timer used to delay termination of the worker process when an IPC error
  // occured or when Crash() request is pending
  base::OneShotTimer kill_process_timer_;

  // The default timeout for |kill_process_timer_|.
  base::TimeDelta kill_process_timeout_;

  // State used to backoff worker launch attempts on failure.
  net::BackoffEntry launch_backoff_;

  // Timer used to schedule the next attempt to launch the process.
  base::OneShotTimer launch_timer_;

  // Monitors |worker_process_| to detect when the launched process
  // terminates.
  base::win::ObjectWatcher process_watcher_;

  // Timer used to detect whether a launch attempt was successful or not, and to
  // cancel the launch attempt if it is taking too long.
  base::OneShotTimer launch_result_timer_;

  // The handle of the worker process, if launched.
  base::win::ScopedHandle worker_process_;

  DISALLOW_COPY_AND_ASSIGN(WorkerProcessLauncher);
};

}  // namespace remoting

#endif  // REMOTING_HOST_WIN_WORKER_PROCESS_LAUNCHER_H_