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

Side by Side Diff: base/process/launch_posix.cc

Issue 114603009: posix LaunchProcess: Don't use STL iterators after fork. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 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
« no previous file with comments | « base/posix/file_descriptor_shuffle.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 static const char kFDDir[] = "/dev/fd"; 200 static const char kFDDir[] = "/dev/fd";
201 #elif defined(OS_FREEBSD) 201 #elif defined(OS_FREEBSD)
202 static const char kFDDir[] = "/dev/fd"; 202 static const char kFDDir[] = "/dev/fd";
203 #elif defined(OS_OPENBSD) 203 #elif defined(OS_OPENBSD)
204 static const char kFDDir[] = "/dev/fd"; 204 static const char kFDDir[] = "/dev/fd";
205 #elif defined(OS_ANDROID) 205 #elif defined(OS_ANDROID)
206 static const char kFDDir[] = "/proc/self/fd"; 206 static const char kFDDir[] = "/proc/self/fd";
207 #endif 207 #endif
208 208
209 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { 209 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
210 // DANGER: no calls to malloc are allowed from now on: 210 // DANGER: no calls to malloc or locks are allowed from now on:
211 // http://crbug.com/36678 211 // http://crbug.com/36678
212 212
213 // Get the maximum number of FDs possible. 213 // Get the maximum number of FDs possible.
214 size_t max_fds = GetMaxFds(); 214 size_t max_fds = GetMaxFds();
215 215
216 DirReaderPosix fd_dir(kFDDir); 216 DirReaderPosix fd_dir(kFDDir);
217 if (!fd_dir.IsValid()) { 217 if (!fd_dir.IsValid()) {
218 // Fallback case: Try every possible fd. 218 // Fallback case: Try every possible fd.
219 for (size_t i = 0; i < max_fds; ++i) { 219 for (size_t i = 0; i < max_fds; ++i) {
220 const int fd = static_cast<int>(i); 220 const int fd = static_cast<int>(i);
221 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 221 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
222 continue; 222 continue;
223 InjectiveMultimap::const_iterator j; 223 // Cannot use STL iterators here, since debug iterators use locks.
224 for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) { 224 size_t j;
225 if (fd == j->dest) 225 for (j = 0; j < saved_mapping.size(); j++) {
226 if (fd == saved_mapping[j].dest)
226 break; 227 break;
227 } 228 }
228 if (j != saved_mapping.end()) 229 if (j < saved_mapping.size())
229 continue; 230 continue;
230 231
231 // Since we're just trying to close anything we can find, 232 // Since we're just trying to close anything we can find,
232 // ignore any error return values of close(). 233 // ignore any error return values of close().
233 close(fd); 234 close(fd);
234 } 235 }
235 return; 236 return;
236 } 237 }
237 238
238 const int dir_fd = fd_dir.fd(); 239 const int dir_fd = fd_dir.fd();
239 240
240 for ( ; fd_dir.Next(); ) { 241 for ( ; fd_dir.Next(); ) {
241 // Skip . and .. entries. 242 // Skip . and .. entries.
242 if (fd_dir.name()[0] == '.') 243 if (fd_dir.name()[0] == '.')
243 continue; 244 continue;
244 245
245 char *endptr; 246 char *endptr;
246 errno = 0; 247 errno = 0;
247 const long int fd = strtol(fd_dir.name(), &endptr, 10); 248 const long int fd = strtol(fd_dir.name(), &endptr, 10);
248 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno) 249 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
249 continue; 250 continue;
250 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 251 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
251 continue; 252 continue;
252 InjectiveMultimap::const_iterator i; 253 // Cannot use STL iterators here, since debug iterators use locks.
253 for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) { 254 size_t i;
254 if (fd == i->dest) 255 for (i = 0; i < saved_mapping.size(); i++) {
256 if (fd == saved_mapping[i].dest)
255 break; 257 break;
256 } 258 }
257 if (i != saved_mapping.end()) 259 if (i < saved_mapping.size())
258 continue; 260 continue;
259 if (fd == dir_fd) 261 if (fd == dir_fd)
260 continue; 262 continue;
261 263
262 // When running under Valgrind, Valgrind opens several FDs for its 264 // When running under Valgrind, Valgrind opens several FDs for its
263 // own use and will complain if we try to close them. All of 265 // own use and will complain if we try to close them. All of
264 // these FDs are >= |max_fds|, so we can check against that here 266 // these FDs are >= |max_fds|, so we can check against that here
265 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 267 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758
266 if (fd < static_cast<int>(max_fds)) { 268 if (fd < static_cast<int>(max_fds)) {
267 int ret = IGNORE_EINTR(close(fd)); 269 int ret = IGNORE_EINTR(close(fd));
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 383
382 #if 0 384 #if 0
383 // When debugging it can be helpful to check that we really aren't making 385 // When debugging it can be helpful to check that we really aren't making
384 // any hidden calls to malloc. 386 // any hidden calls to malloc.
385 void *malloc_thunk = 387 void *malloc_thunk =
386 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); 388 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
387 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); 389 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
388 memset(reinterpret_cast<void*>(malloc), 0xff, 8); 390 memset(reinterpret_cast<void*>(malloc), 0xff, 8);
389 #endif // 0 391 #endif // 0
390 392
391 // DANGER: no calls to malloc are allowed from now on: 393 // DANGER: no calls to malloc or locks are allowed from now on:
392 // http://crbug.com/36678 394 // http://crbug.com/36678
393 395
394 #if defined(OS_CHROMEOS) 396 #if defined(OS_CHROMEOS)
395 if (options.ctrl_terminal_fd >= 0) { 397 if (options.ctrl_terminal_fd >= 0) {
396 // Set process' controlling terminal. 398 // Set process' controlling terminal.
397 if (HANDLE_EINTR(setsid()) != -1) { 399 if (HANDLE_EINTR(setsid()) != -1) {
398 if (HANDLE_EINTR( 400 if (HANDLE_EINTR(
399 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { 401 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) {
400 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); 402 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set");
401 } 403 }
402 } else { 404 } else {
403 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); 405 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set");
404 } 406 }
405 } 407 }
406 #endif // defined(OS_CHROMEOS) 408 #endif // defined(OS_CHROMEOS)
407 409
408 if (options.fds_to_remap) { 410 if (options.fds_to_remap) {
409 for (FileHandleMappingVector::const_iterator 411 // Cannot use STL iterators here, since debug iterators use locks.
410 it = options.fds_to_remap->begin(); 412 for (size_t i = 0; i < options.fds_to_remap->size(); ++i) {
411 it != options.fds_to_remap->end(); ++it) { 413 const FileHandleMappingVector::value_type& value =
412 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false)); 414 (*options.fds_to_remap)[i];
413 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false)); 415 fd_shuffle1.push_back(InjectionArc(value.first, value.second, false));
416 fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
414 } 417 }
415 } 418 }
416 419
417 if (!options.environ.empty()) 420 if (!options.environ.empty())
418 SetEnvironment(new_environ.get()); 421 SetEnvironment(new_environ.get());
419 422
420 // fd_shuffle1 is mutated by this call because it cannot malloc. 423 // fd_shuffle1 is mutated by this call because it cannot malloc.
421 if (!ShuffleFileDescriptors(&fd_shuffle1)) 424 if (!ShuffleFileDescriptors(&fd_shuffle1))
422 _exit(127); 425 _exit(127);
423 426
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 switch (pid = fork()) { 517 switch (pid = fork()) {
515 case -1: // error 518 case -1: // error
516 close(pipe_fd[0]); 519 close(pipe_fd[0]);
517 close(pipe_fd[1]); 520 close(pipe_fd[1]);
518 return EXECUTE_FAILURE; 521 return EXECUTE_FAILURE;
519 case 0: // child 522 case 0: // child
520 { 523 {
521 #if defined(OS_MACOSX) 524 #if defined(OS_MACOSX)
522 RestoreDefaultExceptionHandler(); 525 RestoreDefaultExceptionHandler();
523 #endif 526 #endif
524 // DANGER: no calls to malloc are allowed from now on: 527 // DANGER: no calls to malloc or locks are allowed from now on:
525 // http://crbug.com/36678 528 // http://crbug.com/36678
526 529
527 // Obscure fork() rule: in the child, if you don't end up doing exec*(), 530 // Obscure fork() rule: in the child, if you don't end up doing exec*(),
528 // you call _exit() instead of exit(). This is because _exit() does not 531 // you call _exit() instead of exit(). This is because _exit() does not
529 // call any previously-registered (in the parent) exit handlers, which 532 // call any previously-registered (in the parent) exit handlers, which
530 // might do things like block waiting for threads that don't even exist 533 // might do things like block waiting for threads that don't even exist
531 // in the child. 534 // in the child.
532 int dev_null = open("/dev/null", O_WRONLY); 535 int dev_null = open("/dev/null", O_WRONLY);
533 if (dev_null < 0) 536 if (dev_null < 0)
534 _exit(127); 537 _exit(127);
535 538
536 // Stop type-profiler. 539 // Stop type-profiler.
537 // The profiler should be stopped between fork and exec since it inserts 540 // The profiler should be stopped between fork and exec since it inserts
538 // locks at new/delete expressions. See http://crbug.com/36678. 541 // locks at new/delete expressions. See http://crbug.com/36678.
539 base::type_profiler::Controller::Stop(); 542 base::type_profiler::Controller::Stop();
540 543
541 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); 544 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
542 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); 545 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
543 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); 546 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
544 // Adding another element here? Remeber to increase the argument to 547 // Adding another element here? Remeber to increase the argument to
545 // reserve(), above. 548 // reserve(), above.
546 549
547 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(), 550 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
Elliot Glaysher 2014/01/07 22:33:14 So maybe I'm wrong here, but isn't this using stl
mattm 2014/01/07 22:43:40 Oh, yeah. I missed this one and I must not have be
548 std::back_inserter(fd_shuffle2)); 551 std::back_inserter(fd_shuffle2));
549 552
550 if (!ShuffleFileDescriptors(&fd_shuffle1)) 553 if (!ShuffleFileDescriptors(&fd_shuffle1))
551 _exit(127); 554 _exit(127);
552 555
553 CloseSuperfluousFds(fd_shuffle2); 556 CloseSuperfluousFds(fd_shuffle2);
554 557
555 for (size_t i = 0; i < argv.size(); i++) 558 for (size_t i = 0; i < argv.size(); i++)
556 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); 559 argv_cstr[i] = const_cast<char*>(argv[i].c_str());
557 argv_cstr[argv.size()] = NULL; 560 argv_cstr[argv.size()] = NULL;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 std::string* output, 632 std::string* output,
630 int* exit_code) { 633 int* exit_code) {
631 // Run |execve()| with the current environment and store "unlimited" data. 634 // Run |execve()| with the current environment and store "unlimited" data.
632 GetAppOutputInternalResult result = GetAppOutputInternal( 635 GetAppOutputInternalResult result = GetAppOutputInternal(
633 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true, 636 cl.argv(), NULL, output, std::numeric_limits<std::size_t>::max(), true,
634 exit_code); 637 exit_code);
635 return result == EXECUTE_SUCCESS; 638 return result == EXECUTE_SUCCESS;
636 } 639 }
637 640
638 } // namespace base 641 } // namespace base
OLDNEW
« no previous file with comments | « base/posix/file_descriptor_shuffle.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698