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 |