Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: base/process_util_win.cc

Issue 9700038: ScopedProcessInformation protects against process/thread handle leaks from CreateProcess calls. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to comments. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 <fcntl.h> 7 #include <fcntl.h>
8 #include <io.h> 8 #include <io.h>
9 #include <windows.h> 9 #include <windows.h>
10 #include <userenv.h> 10 #include <userenv.h>
11 #include <psapi.h> 11 #include <psapi.h>
12 12
13 #include <ios> 13 #include <ios>
14 14
15 #include "base/bind.h" 15 #include "base/bind.h"
16 #include "base/bind_helpers.h" 16 #include "base/bind_helpers.h"
17 #include "base/command_line.h" 17 #include "base/command_line.h"
18 #include "base/debug/stack_trace.h" 18 #include "base/debug/stack_trace.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop.h" 21 #include "base/message_loop.h"
22 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
23 #include "base/sys_info.h" 23 #include "base/sys_info.h"
24 #include "base/win/object_watcher.h" 24 #include "base/win/object_watcher.h"
25 #include "base/win/scoped_handle.h" 25 #include "base/win/scoped_handle.h"
26 #include "base/win/scoped_process_information.h"
26 #include "base/win/windows_version.h" 27 #include "base/win/windows_version.h"
27 28
28 // userenv.dll is required for CreateEnvironmentBlock(). 29 // userenv.dll is required for CreateEnvironmentBlock().
29 #pragma comment(lib, "userenv.lib") 30 #pragma comment(lib, "userenv.lib")
30 31
31 namespace base { 32 namespace base {
32 33
33 namespace { 34 namespace {
34 35
35 // System pagesize. This value remains constant on x86/64 architectures. 36 // System pagesize. This value remains constant on x86/64 architectures.
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 300
300 bool LaunchProcess(const string16& cmdline, 301 bool LaunchProcess(const string16& cmdline,
301 const LaunchOptions& options, 302 const LaunchOptions& options,
302 ProcessHandle* process_handle) { 303 ProcessHandle* process_handle) {
303 STARTUPINFO startup_info = {}; 304 STARTUPINFO startup_info = {};
304 startup_info.cb = sizeof(startup_info); 305 startup_info.cb = sizeof(startup_info);
305 if (options.empty_desktop_name) 306 if (options.empty_desktop_name)
306 startup_info.lpDesktop = L""; 307 startup_info.lpDesktop = L"";
307 startup_info.dwFlags = STARTF_USESHOWWINDOW; 308 startup_info.dwFlags = STARTF_USESHOWWINDOW;
308 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW; 309 startup_info.wShowWindow = options.start_hidden ? SW_HIDE : SW_SHOW;
309 PROCESS_INFORMATION process_info;
310 310
311 DWORD flags = 0; 311 DWORD flags = 0;
312 312
313 if (options.job_handle) { 313 if (options.job_handle) {
314 flags |= CREATE_SUSPENDED; 314 flags |= CREATE_SUSPENDED;
315 315
316 // If this code is run under a debugger, the launched process is 316 // If this code is run under a debugger, the launched process is
317 // automatically associated with a job object created by the debugger. 317 // automatically associated with a job object created by the debugger.
318 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. 318 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this.
319 flags |= CREATE_BREAKAWAY_FROM_JOB; 319 flags |= CREATE_BREAKAWAY_FROM_JOB;
320 } 320 }
321 321
322 base::win::ScopedProcessInformation process_info;
323
322 if (options.as_user) { 324 if (options.as_user) {
323 flags |= CREATE_UNICODE_ENVIRONMENT; 325 flags |= CREATE_UNICODE_ENVIRONMENT;
324 void* enviroment_block = NULL; 326 void* enviroment_block = NULL;
325 327
326 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE)) 328 if (!CreateEnvironmentBlock(&enviroment_block, options.as_user, FALSE))
327 return false; 329 return false;
328 330
329 BOOL launched = 331 BOOL launched =
330 CreateProcessAsUser(options.as_user, NULL, 332 CreateProcessAsUser(options.as_user, NULL,
331 const_cast<wchar_t*>(cmdline.c_str()), 333 const_cast<wchar_t*>(cmdline.c_str()),
332 NULL, NULL, options.inherit_handles, flags, 334 NULL, NULL, options.inherit_handles, flags,
333 enviroment_block, NULL, &startup_info, 335 enviroment_block, NULL, &startup_info,
334 &process_info); 336 process_info.Receive());
335 DestroyEnvironmentBlock(enviroment_block); 337 DestroyEnvironmentBlock(enviroment_block);
336 if (!launched) 338 if (!launched)
337 return false; 339 return false;
338 } else { 340 } else {
339 if (!CreateProcess(NULL, 341 if (!CreateProcess(NULL,
340 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL, 342 const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,
341 options.inherit_handles, flags, NULL, NULL, 343 options.inherit_handles, flags, NULL, NULL,
342 &startup_info, &process_info)) { 344 &startup_info, process_info.Receive())) {
343 return false; 345 return false;
344 } 346 }
345 } 347 }
346 348
347 if (options.job_handle) { 349 if (options.job_handle) {
348 if (0 == AssignProcessToJobObject(options.job_handle, 350 if (0 == AssignProcessToJobObject(options.job_handle,
349 process_info.hProcess)) { 351 process_info.Get().hProcess)) {
350 DLOG(ERROR) << "Could not AssignProcessToObject."; 352 DLOG(ERROR) << "Could not AssignProcessToObject.";
351 KillProcess(process_info.hProcess, kProcessKilledExitCode, true); 353 KillProcess(process_info.Get().hProcess, kProcessKilledExitCode, true);
352 return false; 354 return false;
353 } 355 }
354 356
355 ResumeThread(process_info.hThread); 357 ResumeThread(process_info.Get().hThread);
356 } 358 }
357 359
358 // Handles must be closed or they will leak.
359 CloseHandle(process_info.hThread);
360
361 if (options.wait) 360 if (options.wait)
362 WaitForSingleObject(process_info.hProcess, INFINITE); 361 WaitForSingleObject(process_info.Get().hProcess, INFINITE);
363 362
364 // If the caller wants the process handle, we won't close it. 363 // If the caller wants the process handle, we won't close it.
365 if (process_handle) { 364 if (process_handle)
366 *process_handle = process_info.hProcess; 365 *process_handle = process_info.TakeProcessHandle();
367 } else { 366
368 CloseHandle(process_info.hProcess);
369 }
370 return true; 367 return true;
371 } 368 }
372 369
373 bool LaunchProcess(const CommandLine& cmdline, 370 bool LaunchProcess(const CommandLine& cmdline,
374 const LaunchOptions& options, 371 const LaunchOptions& options,
375 ProcessHandle* process_handle) { 372 ProcessHandle* process_handle) {
376 return LaunchProcess(cmdline.GetCommandLineString(), options, process_handle); 373 return LaunchProcess(cmdline.GetCommandLineString(), options, process_handle);
377 } 374 }
378 375
379 bool SetJobObjectAsKillOnJobClose(HANDLE job_object) { 376 bool SetJobObjectAsKillOnJobClose(HANDLE job_object) {
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 999
1003 PERFORMANCE_INFORMATION info; 1000 PERFORMANCE_INFORMATION info;
1004 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { 1001 if (!InternalGetPerformanceInfo(&info, sizeof(info))) {
1005 DLOG(ERROR) << "Failed to fetch internal performance info."; 1002 DLOG(ERROR) << "Failed to fetch internal performance info.";
1006 return 0; 1003 return 0;
1007 } 1004 }
1008 return (info.CommitTotal * system_info.dwPageSize) / 1024; 1005 return (info.CommitTotal * system_info.dwPageSize) / 1024;
1009 } 1006 }
1010 1007
1011 } // namespace base 1008 } // namespace base
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/win/scoped_handle.h » ('j') | base/win/scoped_handle.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698