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/test/multiprocess_test.h" 6 7#include <unistd.h> 8 9#include "base/containers/hash_tables.h" 10#include "base/logging.h" 11#include "testing/multiprocess_func_list.h" 12 13namespace base { 14 15// A very basic implementation for Android. On Android tests can run in an APK 16// and we don't have an executable to exec*. This implementation does the bare 17// minimum to execute the method specified by procname (in the child process). 18// - All options except |fds_to_remap| are ignored. 19// - |debug_on_start| is ignored. 20ProcessHandle MultiProcessTest::SpawnChildWithOptions( 21 const std::string& procname, 22 const LaunchOptions& options, 23 bool debug_on_start) { 24 // TODO(vtl): The FD-remapping done below is wrong in the presence of cycles 25 // (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 stdin, stdout and stderr open since this is not meant to spawn a 47 // daemon. 48 const int kFdForAndroidLogging = 3; // FD used by __android_log_write(). 49 for (int fd = kFdForAndroidLogging + 1; fd < getdtablesize(); ++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