| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/process_util.h" | 5 #include "base/process_util.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <winternl.h> | 8 #include <winternl.h> |
| 9 #include <psapi.h> | 9 #include <psapi.h> |
| 10 | 10 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 | 153 |
| 154 bool LaunchApp(const CommandLine& cl, | 154 bool LaunchApp(const CommandLine& cl, |
| 155 bool wait, bool start_hidden, ProcessHandle* process_handle) { | 155 bool wait, bool start_hidden, ProcessHandle* process_handle) { |
| 156 return LaunchApp(cl.command_line_string(), wait, | 156 return LaunchApp(cl.command_line_string(), wait, |
| 157 start_hidden, process_handle); | 157 start_hidden, process_handle); |
| 158 } | 158 } |
| 159 | 159 |
| 160 // Attempts to kill the process identified by the given process | 160 // Attempts to kill the process identified by the given process |
| 161 // entry structure, giving it the specified exit code. | 161 // entry structure, giving it the specified exit code. |
| 162 // Returns true if this is successful, false otherwise. | 162 // Returns true if this is successful, false otherwise. |
| 163 bool KillProcess(int process_id, int exit_code, bool wait) { | 163 bool KillProcessById(DWORD process_id, int exit_code, bool wait) { |
| 164 HANDLE process = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, | 164 HANDLE process = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, |
| 165 FALSE, // Don't inherit handle | 165 FALSE, // Don't inherit handle |
| 166 process_id); | 166 process_id); |
| 167 if (process) | 167 if (!process) |
| 168 return KillProcess(process, exit_code, wait); | 168 return false; |
| 169 return false; | 169 |
| 170 bool ret = KillProcess(process, exit_code, wait); |
| 171 CloseHandle(process); |
| 172 return ret; |
| 170 } | 173 } |
| 171 | 174 |
| 172 bool KillProcess(HANDLE process, int exit_code, bool wait) { | 175 bool KillProcess(ProcessHandle process, int exit_code, bool wait) { |
| 173 bool result = !!TerminateProcess(process, exit_code); | 176 bool result = (TerminateProcess(process, exit_code) != FALSE); |
| 174 if (result && wait) { | 177 if (result && wait) { |
| 175 // The process may not end immediately due to pending I/O | 178 // The process may not end immediately due to pending I/O |
| 176 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000)) | 179 if (WAIT_OBJECT_0 != WaitForSingleObject(process, 60 * 1000)) |
| 177 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError(); | 180 DLOG(ERROR) << "Error waiting for process exit: " << GetLastError(); |
| 178 } else { | 181 } else { |
| 179 DLOG(ERROR) << "Unable to terminate process: " << GetLastError(); | 182 DLOG(ERROR) << "Unable to terminate process: " << GetLastError(); |
| 180 } | 183 } |
| 181 CloseHandle(process); | |
| 182 return result; | 184 return result; |
| 183 } | 185 } |
| 184 | 186 |
| 185 bool DidProcessCrash(ProcessHandle handle) { | 187 bool DidProcessCrash(ProcessHandle handle) { |
| 186 DWORD exitcode = 0; | 188 DWORD exitcode = 0; |
| 187 if (!::GetExitCodeProcess(handle, &exitcode)) { | 189 if (!::GetExitCodeProcess(handle, &exitcode)) { |
| 188 NOTREACHED(); | 190 NOTREACHED(); |
| 189 return false; | 191 return false; |
| 190 } | 192 } |
| 191 if (exitcode == STILL_ACTIVE) { | 193 if (exitcode == STILL_ACTIVE) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 return false; | 247 return false; |
| 246 } | 248 } |
| 247 DWORD temp_code; // Don't clobber out-parameters in case of failure. | 249 DWORD temp_code; // Don't clobber out-parameters in case of failure. |
| 248 if (!::GetExitCodeProcess(handle, &temp_code)) | 250 if (!::GetExitCodeProcess(handle, &temp_code)) |
| 249 return false; | 251 return false; |
| 250 *exit_code = temp_code; | 252 *exit_code = temp_code; |
| 251 return true; | 253 return true; |
| 252 } | 254 } |
| 253 | 255 |
| 254 NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name, | 256 NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name, |
| 255 const ProcessFilter* filter) : | 257 const ProcessFilter* filter) |
| 256 started_iteration_(false), | 258 : started_iteration_(false), |
| 257 executable_name_(executable_name), | 259 executable_name_(executable_name), |
| 258 filter_(filter) { | 260 filter_(filter) { |
| 259 snapshot_ = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | 261 snapshot_ = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); |
| 260 } | 262 } |
| 261 | 263 |
| 262 NamedProcessIterator::~NamedProcessIterator() { | 264 NamedProcessIterator::~NamedProcessIterator() { |
| 263 CloseHandle(snapshot_); | 265 CloseHandle(snapshot_); |
| 264 } | 266 } |
| 265 | 267 |
| 266 | 268 |
| 267 const ProcessEntry* NamedProcessIterator::NextProcessEntry() { | 269 const ProcessEntry* NamedProcessIterator::NextProcessEntry() { |
| 268 bool result = false; | 270 bool result = false; |
| 269 do { | 271 do { |
| 270 result = CheckForNextProcess(); | 272 result = CheckForNextProcess(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 ++count; | 310 ++count; |
| 309 return count; | 311 return count; |
| 310 } | 312 } |
| 311 | 313 |
| 312 bool KillProcesses(const std::wstring& executable_name, int exit_code, | 314 bool KillProcesses(const std::wstring& executable_name, int exit_code, |
| 313 const ProcessFilter* filter) { | 315 const ProcessFilter* filter) { |
| 314 bool result = true; | 316 bool result = true; |
| 315 const ProcessEntry* entry; | 317 const ProcessEntry* entry; |
| 316 | 318 |
| 317 NamedProcessIterator iter(executable_name, filter); | 319 NamedProcessIterator iter(executable_name, filter); |
| 318 while (entry = iter.NextProcessEntry()) | 320 while (entry = iter.NextProcessEntry()) { |
| 319 result = KillProcess((*entry).th32ProcessID, exit_code, true) && result; | 321 if (!KillProcessById((*entry).th32ProcessID, exit_code, true)) |
| 322 result = false; |
| 323 } |
| 320 | 324 |
| 321 return result; | 325 return result; |
| 322 } | 326 } |
| 323 | 327 |
| 324 bool WaitForProcessesToExit(const std::wstring& executable_name, | 328 bool WaitForProcessesToExit(const std::wstring& executable_name, |
| 325 int wait_milliseconds, | 329 int wait_milliseconds, |
| 326 const ProcessFilter* filter) { | 330 const ProcessFilter* filter) { |
| 327 const ProcessEntry* entry; | 331 const ProcessEntry* entry; |
| 328 bool result = true; | 332 bool result = true; |
| 329 DWORD start_time = GetTickCount(); | 333 DWORD start_time = GetTickCount(); |
| 330 | 334 |
| 331 NamedProcessIterator iter(executable_name, filter); | 335 NamedProcessIterator iter(executable_name, filter); |
| 332 while (entry = iter.NextProcessEntry()) { | 336 while (entry = iter.NextProcessEntry()) { |
| 333 DWORD remaining_wait = | 337 DWORD remaining_wait = |
| 334 std::max(0, wait_milliseconds - | 338 std::max(0, wait_milliseconds - |
| 335 static_cast<int>(GetTickCount() - start_time)); | 339 static_cast<int>(GetTickCount() - start_time)); |
| 336 HANDLE process = OpenProcess(SYNCHRONIZE, | 340 HANDLE process = OpenProcess(SYNCHRONIZE, |
| 337 FALSE, | 341 FALSE, |
| 338 entry->th32ProcessID); | 342 entry->th32ProcessID); |
| 339 DWORD wait_result = WaitForSingleObject(process, remaining_wait); | 343 DWORD wait_result = WaitForSingleObject(process, remaining_wait); |
| 340 CloseHandle(process); | 344 CloseHandle(process); |
| 341 result = result && (wait_result == WAIT_OBJECT_0); | 345 result = result && (wait_result == WAIT_OBJECT_0); |
| 342 } | 346 } |
| 343 | 347 |
| 344 return result; | 348 return result; |
| 345 } | 349 } |
| 346 | 350 |
| 347 bool WaitForSingleProcess(ProcessHandle handle, int wait_milliseconds) { | 351 bool WaitForSingleProcess(ProcessHandle handle, int wait_milliseconds) { |
| 348 bool retval = WaitForSingleObject(handle, wait_milliseconds) == WAIT_OBJECT_0; | 352 bool retval = WaitForSingleObject(handle, wait_milliseconds) == WAIT_OBJECT_0; |
| 349 CloseHandle(handle); | |
| 350 return retval; | 353 return retval; |
| 351 } | 354 } |
| 352 | 355 |
| 353 bool CleanupProcesses(const std::wstring& executable_name, | 356 bool CleanupProcesses(const std::wstring& executable_name, |
| 354 int wait_milliseconds, | 357 int wait_milliseconds, |
| 355 int exit_code, | 358 int exit_code, |
| 356 const ProcessFilter* filter) { | 359 const ProcessFilter* filter) { |
| 357 bool exited_cleanly = WaitForProcessesToExit(executable_name, | 360 bool exited_cleanly = WaitForProcessesToExit(executable_name, |
| 358 wait_milliseconds, | 361 wait_milliseconds, |
| 359 filter); | 362 filter); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 void EnableTerminationOnHeapCorruption() { | 637 void EnableTerminationOnHeapCorruption() { |
| 635 // Ignore the result code. Supported on XP SP3 and Vista. | 638 // Ignore the result code. Supported on XP SP3 and Vista. |
| 636 HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); | 639 HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); |
| 637 } | 640 } |
| 638 | 641 |
| 639 void RaiseProcessToHighPriority() { | 642 void RaiseProcessToHighPriority() { |
| 640 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | 643 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); |
| 641 } | 644 } |
| 642 | 645 |
| 643 } // namespace base | 646 } // namespace base |
| OLD | NEW |