| OLD | NEW |
| 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/launch.h" | 5 #include "base/process/launch.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <signal.h> | 10 #include <signal.h> |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 if (pid != 0) { | 313 if (pid != 0) { |
| 314 SetSignalMask(orig_sigmask); | 314 SetSignalMask(orig_sigmask); |
| 315 } | 315 } |
| 316 | 316 |
| 317 if (pid < 0) { | 317 if (pid < 0) { |
| 318 DPLOG(ERROR) << "fork"; | 318 DPLOG(ERROR) << "fork"; |
| 319 return false; | 319 return false; |
| 320 } else if (pid == 0) { | 320 } else if (pid == 0) { |
| 321 // Child process | 321 // Child process |
| 322 | 322 |
| 323 // DANGER: no calls to malloc or locks are allowed from now on: |
| 324 // http://crbug.com/36678 |
| 325 |
| 323 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), | 326 // DANGER: fork() rule: in the child, if you don't end up doing exec*(), |
| 324 // you call _exit() instead of exit(). This is because _exit() does not | 327 // you call _exit() instead of exit(). This is because _exit() does not |
| 325 // call any previously-registered (in the parent) exit handlers, which | 328 // call any previously-registered (in the parent) exit handlers, which |
| 326 // might do things like block waiting for threads that don't even exist | 329 // might do things like block waiting for threads that don't even exist |
| 327 // in the child. | 330 // in the child. |
| 328 | 331 |
| 329 // If a child process uses the readline library, the process block forever. | 332 // If a child process uses the readline library, the process block forever. |
| 330 // In BSD like OSes including OS X it is safe to assign /dev/null as stdin. | 333 // In BSD like OSes including OS X it is safe to assign /dev/null as stdin. |
| 331 // See http://crbug.com/56596. | 334 // See http://crbug.com/56596. |
| 332 int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY)); | 335 int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 351 } | 354 } |
| 352 } | 355 } |
| 353 | 356 |
| 354 // Stop type-profiler. | 357 // Stop type-profiler. |
| 355 // The profiler should be stopped between fork and exec since it inserts | 358 // The profiler should be stopped between fork and exec since it inserts |
| 356 // locks at new/delete expressions. See http://crbug.com/36678. | 359 // locks at new/delete expressions. See http://crbug.com/36678. |
| 357 base::type_profiler::Controller::Stop(); | 360 base::type_profiler::Controller::Stop(); |
| 358 | 361 |
| 359 if (options.maximize_rlimits) { | 362 if (options.maximize_rlimits) { |
| 360 // Some resource limits need to be maximal in this child. | 363 // Some resource limits need to be maximal in this child. |
| 361 std::set<int>::const_iterator resource; | 364 for (size_t i = 0; i < options.maximize_rlimits->size(); ++i) { |
| 362 for (resource = options.maximize_rlimits->begin(); | 365 const int resource = (*options.maximize_rlimits)[i]; |
| 363 resource != options.maximize_rlimits->end(); | |
| 364 ++resource) { | |
| 365 struct rlimit limit; | 366 struct rlimit limit; |
| 366 if (getrlimit(*resource, &limit) < 0) { | 367 if (getrlimit(resource, &limit) < 0) { |
| 367 RAW_LOG(WARNING, "getrlimit failed"); | 368 RAW_LOG(WARNING, "getrlimit failed"); |
| 368 } else if (limit.rlim_cur < limit.rlim_max) { | 369 } else if (limit.rlim_cur < limit.rlim_max) { |
| 369 limit.rlim_cur = limit.rlim_max; | 370 limit.rlim_cur = limit.rlim_max; |
| 370 if (setrlimit(*resource, &limit) < 0) { | 371 if (setrlimit(resource, &limit) < 0) { |
| 371 RAW_LOG(WARNING, "setrlimit failed"); | 372 RAW_LOG(WARNING, "setrlimit failed"); |
| 372 } | 373 } |
| 373 } | 374 } |
| 374 } | 375 } |
| 375 } | 376 } |
| 376 | 377 |
| 377 #if defined(OS_MACOSX) | 378 #if defined(OS_MACOSX) |
| 378 RestoreDefaultExceptionHandler(); | 379 RestoreDefaultExceptionHandler(); |
| 379 #endif // defined(OS_MACOSX) | 380 #endif // defined(OS_MACOSX) |
| 380 | 381 |
| 381 ResetChildSignalHandlersToDefaults(); | 382 ResetChildSignalHandlersToDefaults(); |
| 382 SetSignalMask(orig_sigmask); | 383 SetSignalMask(orig_sigmask); |
| 383 | 384 |
| 384 #if 0 | 385 #if 0 |
| 385 // When debugging it can be helpful to check that we really aren't making | 386 // When debugging it can be helpful to check that we really aren't making |
| 386 // any hidden calls to malloc. | 387 // any hidden calls to malloc. |
| 387 void *malloc_thunk = | 388 void *malloc_thunk = |
| 388 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 389 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
| 389 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 390 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
| 390 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 391 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
| 391 #endif // 0 | 392 #endif // 0 |
| 392 | 393 |
| 393 // DANGER: no calls to malloc or locks are allowed from now on: | |
| 394 // http://crbug.com/36678 | |
| 395 | |
| 396 #if defined(OS_CHROMEOS) | 394 #if defined(OS_CHROMEOS) |
| 397 if (options.ctrl_terminal_fd >= 0) { | 395 if (options.ctrl_terminal_fd >= 0) { |
| 398 // Set process' controlling terminal. | 396 // Set process' controlling terminal. |
| 399 if (HANDLE_EINTR(setsid()) != -1) { | 397 if (HANDLE_EINTR(setsid()) != -1) { |
| 400 if (HANDLE_EINTR( | 398 if (HANDLE_EINTR( |
| 401 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { | 399 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { |
| 402 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); | 400 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); |
| 403 } | 401 } |
| 404 } else { | 402 } else { |
| 405 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); | 403 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 if (pipe(pipe_fd) < 0) | 512 if (pipe(pipe_fd) < 0) |
| 515 return EXECUTE_FAILURE; | 513 return EXECUTE_FAILURE; |
| 516 | 514 |
| 517 switch (pid = fork()) { | 515 switch (pid = fork()) { |
| 518 case -1: // error | 516 case -1: // error |
| 519 close(pipe_fd[0]); | 517 close(pipe_fd[0]); |
| 520 close(pipe_fd[1]); | 518 close(pipe_fd[1]); |
| 521 return EXECUTE_FAILURE; | 519 return EXECUTE_FAILURE; |
| 522 case 0: // child | 520 case 0: // child |
| 523 { | 521 { |
| 522 // DANGER: no calls to malloc or locks are allowed from now on: |
| 523 // http://crbug.com/36678 |
| 524 |
| 524 #if defined(OS_MACOSX) | 525 #if defined(OS_MACOSX) |
| 525 RestoreDefaultExceptionHandler(); | 526 RestoreDefaultExceptionHandler(); |
| 526 #endif | 527 #endif |
| 527 // DANGER: no calls to malloc or locks are allowed from now on: | |
| 528 // http://crbug.com/36678 | |
| 529 | 528 |
| 530 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 529 // Obscure fork() rule: in the child, if you don't end up doing exec*(), |
| 531 // you call _exit() instead of exit(). This is because _exit() does not | 530 // you call _exit() instead of exit(). This is because _exit() does not |
| 532 // call any previously-registered (in the parent) exit handlers, which | 531 // call any previously-registered (in the parent) exit handlers, which |
| 533 // might do things like block waiting for threads that don't even exist | 532 // might do things like block waiting for threads that don't even exist |
| 534 // in the child. | 533 // in the child. |
| 535 int dev_null = open("/dev/null", O_WRONLY); | 534 int dev_null = open("/dev/null", O_WRONLY); |
| 536 if (dev_null < 0) | 535 if (dev_null < 0) |
| 537 _exit(127); | 536 _exit(127); |
| 538 | 537 |
| 539 // Stop type-profiler. | 538 // Stop type-profiler. |
| 540 // The profiler should be stopped between fork and exec since it inserts | 539 // The profiler should be stopped between fork and exec since it inserts |
| 541 // locks at new/delete expressions. See http://crbug.com/36678. | 540 // locks at new/delete expressions. See http://crbug.com/36678. |
| 542 base::type_profiler::Controller::Stop(); | 541 base::type_profiler::Controller::Stop(); |
| 543 | 542 |
| 544 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); | 543 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
| 545 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); | 544 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); |
| 546 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); | 545 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
| 547 // Adding another element here? Remeber to increase the argument to | 546 // Adding another element here? Remeber to increase the argument to |
| 548 // reserve(), above. | 547 // reserve(), above. |
| 549 | 548 |
| 550 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), | 549 for (size_t i = 0; i < fd_shuffle1.size(); ++i) |
| 551 std::back_inserter(fd_shuffle2)); | 550 fd_shuffle2.push_back(fd_shuffle1[i]); |
| 552 | 551 |
| 553 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 552 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
| 554 _exit(127); | 553 _exit(127); |
| 555 | 554 |
| 556 CloseSuperfluousFds(fd_shuffle2); | 555 CloseSuperfluousFds(fd_shuffle2); |
| 557 | 556 |
| 558 for (size_t i = 0; i < argv.size(); i++) | 557 for (size_t i = 0; i < argv.size(); i++) |
| 559 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 558 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 560 argv_cstr[argv.size()] = NULL; | 559 argv_cstr[argv.size()] = NULL; |
| 561 if (do_search_path) | 560 if (do_search_path) |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 std::string* output, | 631 std::string* output, |
| 633 int* exit_code) { | 632 int* exit_code) { |
| 634 // Run |execve()| with the current environment and store "unlimited" data. | 633 // Run |execve()| with the current environment and store "unlimited" data. |
| 635 GetAppOutputInternalResult result = GetAppOutputInternal( | 634 GetAppOutputInternalResult result = GetAppOutputInternal( |
| 636 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, | 635 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, |
| 637 exit_code); | 636 exit_code); |
| 638 return result == EXECUTE_SUCCESS; | 637 return result == EXECUTE_SUCCESS; |
| 639 } | 638 } |
| 640 | 639 |
| 641 } // namespace base | 640 } // namespace base |
| OLD | NEW |