| 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 #include "components/browser_watcher/window_hang_monitor_win.h" | 5 #include "components/browser_watcher/window_hang_monitor_win.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 } | 89 } |
| 90 return reinterpret_cast<HANDLE>(switch_uint); | 90 return reinterpret_cast<HANDLE>(switch_uint); |
| 91 } | 91 } |
| 92 | 92 |
| 93 // An instance of this class lives in the monitored process and receives signals | 93 // An instance of this class lives in the monitored process and receives signals |
| 94 // and executes their associated function. | 94 // and executes their associated function. |
| 95 class MonitoredProcessClient { | 95 class MonitoredProcessClient { |
| 96 public: | 96 public: |
| 97 MonitoredProcessClient() | 97 MonitoredProcessClient() |
| 98 : message_window_thread_("Message window thread"), | 98 : message_window_thread_("Message window thread"), |
| 99 hang_event_(true, false) { | 99 hang_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
| 100 base::WaitableEvent::InitialState::NOT_SIGNALED) { |
| 100 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 101 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 101 | 102 |
| 102 read_pipe_.Set(GetSwitchValueHandle(command_line, kChildReadPipeSwitch)); | 103 read_pipe_.Set(GetSwitchValueHandle(command_line, kChildReadPipeSwitch)); |
| 103 write_pipe_.Set(GetSwitchValueHandle(command_line, kChildWritePipeSwitch)); | 104 write_pipe_.Set(GetSwitchValueHandle(command_line, kChildWritePipeSwitch)); |
| 104 } | 105 } |
| 105 | 106 |
| 106 ~MonitoredProcessClient() { | 107 ~MonitoredProcessClient() { |
| 107 if (message_window_thread_.IsRunning()) { | 108 if (message_window_thread_.IsRunning()) { |
| 108 DeleteMessageWindow(); | 109 DeleteMessageWindow(); |
| 109 } | 110 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 136 SendSignalToParent(IPC_SIGNAL_READY); | 137 SendSignalToParent(IPC_SIGNAL_READY); |
| 137 } | 138 } |
| 138 } | 139 } |
| 139 | 140 |
| 140 // Creates a thread then creates the message window on it. | 141 // Creates a thread then creates the message window on it. |
| 141 void CreateMessageWindow() { | 142 void CreateMessageWindow() { |
| 142 ASSERT_TRUE(message_window_thread_.StartWithOptions( | 143 ASSERT_TRUE(message_window_thread_.StartWithOptions( |
| 143 base::Thread::Options(base::MessageLoop::TYPE_UI, 0))); | 144 base::Thread::Options(base::MessageLoop::TYPE_UI, 0))); |
| 144 | 145 |
| 145 bool succeeded = false; | 146 bool succeeded = false; |
| 146 base::WaitableEvent created(true, false); | 147 base::WaitableEvent created( |
| 148 base::WaitableEvent::ResetPolicy::MANUAL, |
| 149 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 147 ASSERT_TRUE(message_window_thread_.task_runner()->PostTask( | 150 ASSERT_TRUE(message_window_thread_.task_runner()->PostTask( |
| 148 FROM_HERE, | 151 FROM_HERE, |
| 149 base::Bind(&MonitoredProcessClient::CreateMessageWindowInWorkerThread, | 152 base::Bind(&MonitoredProcessClient::CreateMessageWindowInWorkerThread, |
| 150 base::Unretained(this), &succeeded, &created))); | 153 base::Unretained(this), &succeeded, &created))); |
| 151 created.Wait(); | 154 created.Wait(); |
| 152 ASSERT_TRUE(succeeded); | 155 ASSERT_TRUE(succeeded); |
| 153 } | 156 } |
| 154 | 157 |
| 155 // Creates a thread then creates the message window on it. | 158 // Creates a thread then creates the message window on it. |
| 156 void HangMessageWindow() { | 159 void HangMessageWindow() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 185 | 188 |
| 186 message_window_.reset(new base::win::MessageWindow); | 189 message_window_.reset(new base::win::MessageWindow); |
| 187 *success = message_window_->CreateNamed( | 190 *success = message_window_->CreateNamed( |
| 188 base::Bind(&MonitoredProcessClient::EmptyMessageCallback, | 191 base::Bind(&MonitoredProcessClient::EmptyMessageCallback, |
| 189 base::Unretained(this)), | 192 base::Unretained(this)), |
| 190 existing_dir.value().c_str()); | 193 existing_dir.value().c_str()); |
| 191 created->Signal(); | 194 created->Signal(); |
| 192 } | 195 } |
| 193 | 196 |
| 194 void DeleteMessageWindow() { | 197 void DeleteMessageWindow() { |
| 195 base::WaitableEvent deleted(true, false); | 198 base::WaitableEvent deleted( |
| 199 base::WaitableEvent::ResetPolicy::MANUAL, |
| 200 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 196 message_window_thread_.task_runner()->PostTask( | 201 message_window_thread_.task_runner()->PostTask( |
| 197 FROM_HERE, | 202 FROM_HERE, |
| 198 base::Bind(&MonitoredProcessClient::DeleteMessageWindowInWorkerThread, | 203 base::Bind(&MonitoredProcessClient::DeleteMessageWindowInWorkerThread, |
| 199 base::Unretained(this), &deleted)); | 204 base::Unretained(this), &deleted)); |
| 200 deleted.Wait(); | 205 deleted.Wait(); |
| 201 | 206 |
| 202 message_window_thread_.Stop(); | 207 message_window_thread_.Stop(); |
| 203 } | 208 } |
| 204 | 209 |
| 205 void DeleteMessageWindowInWorkerThread(base::WaitableEvent* deleted) { | 210 void DeleteMessageWindowInWorkerThread(base::WaitableEvent* deleted) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 231 | 236 |
| 232 return 0; | 237 return 0; |
| 233 } | 238 } |
| 234 | 239 |
| 235 // Manages a WindowHangMonitor that lives on a background thread. | 240 // Manages a WindowHangMonitor that lives on a background thread. |
| 236 class HangMonitorThread { | 241 class HangMonitorThread { |
| 237 public: | 242 public: |
| 238 // Instantiates the background thread. | 243 // Instantiates the background thread. |
| 239 HangMonitorThread() | 244 HangMonitorThread() |
| 240 : event_(WindowHangMonitor::WINDOW_NOT_FOUND), | 245 : event_(WindowHangMonitor::WINDOW_NOT_FOUND), |
| 241 event_received_(false, false), | 246 event_received_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 247 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 242 thread_("Hang monitor thread") {} | 248 thread_("Hang monitor thread") {} |
| 243 | 249 |
| 244 ~HangMonitorThread() { | 250 ~HangMonitorThread() { |
| 245 if (hang_monitor_.get()) | 251 if (hang_monitor_.get()) |
| 246 DestroyWatcher(); | 252 DestroyWatcher(); |
| 247 } | 253 } |
| 248 | 254 |
| 249 // Starts the background thread and the monitor to observe Chrome message | 255 // Starts the background thread and the monitor to observe Chrome message |
| 250 // window for |process|. Blocks until the monitor has been initialized. | 256 // window for |process|. Blocks until the monitor has been initialized. |
| 251 bool Start(base::Process process) { | 257 bool Start(base::Process process) { |
| 252 if (!thread_.StartWithOptions( | 258 if (!thread_.StartWithOptions( |
| 253 base::Thread::Options(base::MessageLoop::TYPE_UI, 0))) { | 259 base::Thread::Options(base::MessageLoop::TYPE_UI, 0))) { |
| 254 return false; | 260 return false; |
| 255 } | 261 } |
| 256 | 262 |
| 257 base::WaitableEvent complete(false, false); | 263 base::WaitableEvent complete( |
| 264 base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 265 base::WaitableEvent::InitialState::NOT_SIGNALED); |
| 258 if (!thread_.task_runner()->PostTask( | 266 if (!thread_.task_runner()->PostTask( |
| 259 FROM_HERE, | 267 FROM_HERE, |
| 260 base::Bind(&HangMonitorThread::StartupOnThread, | 268 base::Bind(&HangMonitorThread::StartupOnThread, |
| 261 base::Unretained(this), base::Passed(std::move(process)), | 269 base::Unretained(this), base::Passed(std::move(process)), |
| 262 base::Unretained(&complete)))) { | 270 base::Unretained(&complete)))) { |
| 263 return false; | 271 return false; |
| 264 } | 272 } |
| 265 | 273 |
| 266 complete.Wait(); | 274 complete.Wait(); |
| 267 | 275 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 | 468 |
| 461 ASSERT_TRUE(SendSignal(IPC_SIGNAL_HANG_MESSAGE_WINDOW)); | 469 ASSERT_TRUE(SendSignal(IPC_SIGNAL_HANG_MESSAGE_WINDOW)); |
| 462 | 470 |
| 463 EXPECT_EQ(WindowHangMonitor::WINDOW_HUNG, | 471 EXPECT_EQ(WindowHangMonitor::WINDOW_HUNG, |
| 464 monitor_thread().WaitForEvent()); | 472 monitor_thread().WaitForEvent()); |
| 465 | 473 |
| 466 ASSERT_TRUE(SendSignal(IPC_SIGNAL_TERMINATE_PROCESS)); | 474 ASSERT_TRUE(SendSignal(IPC_SIGNAL_TERMINATE_PROCESS)); |
| 467 } | 475 } |
| 468 | 476 |
| 469 } // namespace browser_watcher | 477 } // namespace browser_watcher |
| OLD | NEW |