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 3// found in the LICENSE file. 4 5#include "base/posix/global_descriptors.h" 6#include "base/test/multiprocess_test.h" 7 8#include <unistd.h> 9 10#include "base/containers/hash_tables.h" 11#include "base/logging.h" 12#include "testing/multiprocess_func_list.h" 13 14namespace base { 15 16// A very basic implementation for Android. On Android tests can run in an APK 17// and we don't have an executable to exec*. This implementation does the bare 18// minimum to execute the method specified by procname (in the child process). 19// - |base_command_line| is ignored. 20// - All options except |fds_to_remap| are ignored. 21ProcessHandle SpawnMultiProcessTestChild(const std::string& procname, 22 const CommandLine& base_command_line, 23 const LaunchOptions& options) { 24 // TODO(viettrungluu): The FD-remapping done below is wrong in the presence of 25 // cycles (e.g., fd1 -> fd2, fd2 -> fd1). crbug.com/326576 26 FileHandleMappingVector empty; 27 const FileHandleMappingVector* fds_to_remap = 28 options.fds_to_remap ? options.fds_to_remap : ∅ 29 30 pid_t pid = fork(); 31 32 if (pid < 0) { 33 PLOG(ERROR) << "fork"; 34 return kNullProcessHandle; 35 } 36 if (pid > 0) { 37 // Parent process. 38 return pid; 39 } 40 // Child process. 41 std::hash_set<int> fds_to_keep_open; 42 for (FileHandleMappingVector::const_iterator it = fds_to_remap->begin(); 43 it != fds_to_remap->end(); ++it) { 44 fds_to_keep_open.insert(it->first); 45 } 46 // Keep standard FDs (stdin, stdout, stderr, etc.) open since this 47 // is not meant to spawn a daemon. 48 int base = GlobalDescriptors::kBaseDescriptor; 49 for (int fd = base; fd < sysconf(_SC_OPEN_MAX); ++fd) { 50 if (fds_to_keep_open.find(fd) == fds_to_keep_open.end()) { 51 close(fd); 52 } 53 } 54 for (FileHandleMappingVector::const_iterator it = fds_to_remap->begin(); 55 it != fds_to_remap->end(); ++it) { 56 int old_fd = it->first; 57 int new_fd = it->second; 58 if (dup2(old_fd, new_fd) < 0) { 59 PLOG(FATAL) << "dup2"; 60 } 61 close(old_fd); 62 } 63 _exit(multi_process_function_list::InvokeChildProcessTest(procname)); 64 return 0; 65} 66 67} // namespace base 68