Chromium Code Reviews| Index: base/process_util_win.cc |
| =================================================================== |
| --- base/process_util_win.cc (revision 111236) |
| +++ base/process_util_win.cc (working copy) |
| @@ -16,8 +16,10 @@ |
| #include "base/debug/stack_trace.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| +#include "base/message_loop.h" |
| #include "base/metrics/histogram.h" |
| #include "base/sys_info.h" |
| +#include "base/win/object_watcher.h" |
| #include "base/win/scoped_handle.h" |
| #include "base/win/windows_version.h" |
| @@ -37,6 +39,9 @@ |
| const DWORD kKeyboardInterruptExitCode = 0xC000013A; |
| const DWORD kDebuggerTerminatedExitCode = 0x40010004; |
| +// Maximum amount of time (in milliseconds) to wait for the process to exit. |
| +static const int kWaitInterval = 2000; |
| + |
| // This exit code is used by the Windows task manager when it kills a |
| // process. It's value is obviously not that unique, and it's |
| // surprising to me that the task manager uses this value, but it |
| @@ -103,6 +108,58 @@ |
| _exit(1); |
| } |
| +class TimerExpiredTask : public Task, |
| + public win::ObjectWatcher::Delegate { |
| + public: |
| + explicit TimerExpiredTask(ProcessHandle process) : process_(process) { |
| + watcher_.StartWatching(process_, this); |
| + } |
| + |
| + virtual ~TimerExpiredTask() { |
| + if (process_) { |
| + KillProcess(); |
| + DCHECK(!process_) << "Make sure to close the handle."; |
| + } |
| + } |
| + |
| + // Task --------------------------------------------------------------------- |
| + |
| + virtual void Run() { |
| + if (process_) |
| + KillProcess(); |
| + } |
| + |
| + // MessageLoop::Watcher ----------------------------------------------------- |
| + |
| + virtual void OnObjectSignaled(HANDLE object) { |
| + // When we're called from KillProcess, the ObjectWatcher may still be |
| + // watching. the process handle, so make sure it has stopped. |
| + watcher_.StopWatching(); |
| + |
| + CloseHandle(process_); |
|
cpu_(ooo_6.6-7.5)
2011/11/24 00:22:07
I see a problem, here we close the handle, but we
|
| + process_ = NULL; |
| + } |
| + |
| + private: |
| + void KillProcess() { |
| + // OK, time to get frisky. We don't actually care when the process |
| + // terminates. We just care that it eventually terminates, and that's what |
| + // TerminateProcess should do for us. Don't check for the result code since |
| + // it fails quite often. This should be investigated eventually. |
| + base::KillProcess(process_, kProcessKilledExitCode, false); |
| + |
| + // Now, just cleanup as if the process exited normally. |
| + OnObjectSignaled(process_); |
| + } |
| + |
| + // The process that we are watching. |
| + ProcessHandle process_; |
| + |
| + win::ObjectWatcher watcher_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TimerExpiredTask); |
| +}; |
| + |
| } // namespace |
| ProcessId GetCurrentProcId() { |
| @@ -551,6 +608,20 @@ |
| return exited_cleanly; |
| } |
| +void EnsureProcessTerminated(ProcessHandle process) { |
| + DCHECK(process != GetCurrentProcess()); |
| + |
| + // If already signaled, then we are done! |
| + if (WaitForSingleObject(process, 0) == WAIT_OBJECT_0) { |
| + CloseHandle(process); |
| + return; |
| + } |
| + |
| + MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| + new TimerExpiredTask(process), |
| + kWaitInterval); |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| // ProcesMetrics |