OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 | 5 |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/process_util.h" | 7 #include "base/process_util.h" |
8 | 8 |
9 #import <Cocoa/Cocoa.h> | 9 #import <Cocoa/Cocoa.h> |
10 #include <spawn.h> | 10 #include <spawn.h> |
11 #include <string> | 11 #include <string> |
12 #include <sys/types.h> | 12 #include <sys/types.h> |
13 #include <sys/wait.h> | 13 #include <sys/wait.h> |
14 | 14 |
15 extern "C" { | 15 extern "C" { |
16 extern char** environ; | 16 extern char** environ; |
17 } | 17 } |
18 | 18 |
19 namespace base { | 19 namespace base { |
20 | 20 |
21 bool LaunchApp(const std::vector<std::string>& argv, | 21 bool LaunchApp(const std::vector<std::string>& argv, |
| 22 const file_handle_mapping_vector& fds_to_remap, |
22 bool wait, ProcessHandle* process_handle) { | 23 bool wait, ProcessHandle* process_handle) { |
23 bool retval = true; | 24 bool retval = true; |
24 | 25 |
25 char* argv_copy[argv.size() + 1]; | 26 char* argv_copy[argv.size() + 1]; |
26 for (size_t i = 0; i < argv.size(); i++) { | 27 for (size_t i = 0; i < argv.size(); i++) { |
27 argv_copy[i] = const_cast<char*>(argv[i].c_str()); | 28 argv_copy[i] = const_cast<char*>(argv[i].c_str()); |
28 } | 29 } |
29 argv_copy[argv.size()] = NULL; | 30 argv_copy[argv.size()] = NULL; |
30 | 31 |
| 32 // Make sure we don't leak any FDs to the child process by marking all FDs |
| 33 // as close-on-exec. |
| 34 int max_files = GetMaxFilesOpenInProcess(); |
| 35 for (int i = STDERR_FILENO + 1; i < max_files; i++) { |
| 36 int flags = fcntl(i, F_GETFD); |
| 37 if (flags != -1) { |
| 38 fcntl(i, F_SETFD, flags | FD_CLOEXEC); |
| 39 } |
| 40 } |
| 41 |
| 42 posix_spawn_file_actions_t file_actions; |
| 43 if (posix_spawn_file_actions_init(&file_actions) != 0) { |
| 44 return false; |
| 45 } |
| 46 |
| 47 // Turn fds_to_remap array into a set of dup2 calls. |
| 48 for (file_handle_mapping_vector::const_iterator it = fds_to_remap.begin(); |
| 49 it != fds_to_remap.end(); |
| 50 ++it) { |
| 51 int src_fd = it->first; |
| 52 int dest_fd = it->second; |
| 53 |
| 54 if (src_fd == dest_fd) { |
| 55 int flags = fcntl(src_fd, F_GETFD); |
| 56 if (flags != -1) { |
| 57 fcntl(src_fd, F_SETFD, flags & ~FD_CLOEXEC); |
| 58 } |
| 59 } else { |
| 60 if (posix_spawn_file_actions_adddup2(&file_actions, src_fd, dest_fd) != 0) |
| 61 { |
| 62 posix_spawn_file_actions_destroy(&file_actions); |
| 63 return false; |
| 64 } |
| 65 } |
| 66 } |
| 67 |
31 int pid = 0; | 68 int pid = 0; |
32 int spawn_succeeded = (posix_spawnp(&pid, | 69 int spawn_succeeded = (posix_spawnp(&pid, |
33 argv_copy[0], | 70 argv_copy[0], |
34 NULL, | 71 &file_actions, |
35 NULL, | 72 NULL, |
36 argv_copy, | 73 argv_copy, |
37 environ) == 0); | 74 environ) == 0); |
38 | 75 |
39 bool process_handle_valid = pid > 0; | 76 posix_spawn_file_actions_destroy(&file_actions); |
| 77 |
| 78 bool process_handle_valid = pid > 0; |
40 if (!spawn_succeeded || !process_handle_valid) { | 79 if (!spawn_succeeded || !process_handle_valid) { |
41 retval = false; | 80 retval = false; |
42 } else { | 81 } else { |
43 if (wait) | 82 if (wait) |
44 waitpid(pid, 0, 0); | 83 waitpid(pid, 0, 0); |
45 | 84 |
46 if(process_handle) | 85 if(process_handle) |
47 *process_handle = pid; | 86 *process_handle = pid; |
48 } | 87 } |
49 | 88 |
50 return retval; | 89 return retval; |
51 } | 90 } |
52 | 91 |
53 bool LaunchApp(const CommandLine& cl, | 92 bool LaunchApp(const CommandLine& cl, |
54 bool wait, bool start_hidden, ProcessHandle* process_handle) { | 93 bool wait, bool start_hidden, ProcessHandle* process_handle) { |
55 // TODO(playmobil): Do we need to respect the start_hidden flag? | 94 // TODO(playmobil): Do we need to respect the start_hidden flag? |
56 return LaunchApp(cl.argv(), wait, process_handle); | 95 file_handle_mapping_vector no_files; |
| 96 return LaunchApp(cl.argv(), no_files, wait, process_handle); |
57 } | 97 } |
58 | 98 |
59 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) { | 99 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) { |
60 // TODO(pinkerton): can we implement this? On linux it relies on /proc. | 100 // TODO(pinkerton): can we implement this? On linux it relies on /proc. |
61 return false; | 101 return false; |
62 } | 102 } |
63 | 103 |
64 int GetProcessCount(const std::wstring& executable_name, | 104 int GetProcessCount(const std::wstring& executable_name, |
65 const ProcessFilter* filter) { | 105 const ProcessFilter* filter) { |
66 NOTIMPLEMENTED(); | 106 NOTIMPLEMENTED(); |
67 return 0; | 107 return 0; |
68 } | 108 } |
69 | 109 |
70 bool CleanupProcesses(const std::wstring& executable_name, | 110 bool CleanupProcesses(const std::wstring& executable_name, |
71 int wait_milliseconds, | 111 int wait_milliseconds, |
72 int exit_code, | 112 int exit_code, |
73 const ProcessFilter* filter) { | 113 const ProcessFilter* filter) { |
74 NOTIMPLEMENTED(); | 114 NOTIMPLEMENTED(); |
75 return false; | 115 return false; |
76 } | 116 } |
77 | 117 |
78 } // namespace base | 118 } // namespace base |
OLD | NEW |