OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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 #include <dirent.h> | 5 #include <dirent.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <signal.h> | 8 #include <signal.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <sys/resource.h> | 10 #include <sys/resource.h> |
11 #include <sys/time.h> | 11 #include <sys/time.h> |
12 #include <sys/types.h> | 12 #include <sys/types.h> |
13 #include <sys/wait.h> | 13 #include <sys/wait.h> |
14 #include <unistd.h> | 14 #include <unistd.h> |
15 | 15 |
16 #include <limits> | 16 #include <limits> |
17 #include <set> | 17 #include <set> |
18 | 18 |
19 #include "base/debug_util.h" | 19 #include "base/debug_util.h" |
20 #include "base/eintr_wrapper.h" | 20 #include "base/eintr_wrapper.h" |
21 #include "base/logging.h" | 21 #include "base/logging.h" |
22 #include "base/platform_thread.h" | 22 #include "base/platform_thread.h" |
23 #include "base/process_util.h" | 23 #include "base/process_util.h" |
24 #include "base/scoped_ptr.h" | 24 #include "base/scoped_ptr.h" |
25 #include "base/sys_info.h" | 25 #include "base/sys_info.h" |
26 #include "base/time.h" | 26 #include "base/time.h" |
27 #include "base/waitable_event.h" | 27 #include "base/waitable_event.h" |
28 | 28 |
29 #if defined(OS_MACOSX) | |
30 #include "base/mach_broker_mac.h" | |
31 | |
32 | |
33 #endif | |
34 | |
35 const int kMicrosecondsPerSecond = 1000000; | 29 const int kMicrosecondsPerSecond = 1000000; |
36 | 30 |
37 namespace base { | 31 namespace base { |
38 | 32 |
39 namespace { | 33 namespace { |
40 | 34 |
41 int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, | 35 int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, |
42 bool* success) { | 36 bool* success) { |
43 // This POSIX version of this function only guarantees that we wait no less | 37 // This POSIX version of this function only guarantees that we wait no less |
44 // than |wait_milliseconds| for the proces to exit. The child process may | 38 // than |wait_milliseconds| for the proces to exit. The child process may |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 if (i <= STDERR_FILENO) | 273 if (i <= STDERR_FILENO) |
280 continue; | 274 continue; |
281 | 275 |
282 int flags = fcntl(i, F_GETFD); | 276 int flags = fcntl(i, F_GETFD); |
283 if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { | 277 if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { |
284 DLOG(ERROR) << "fcntl failure."; | 278 DLOG(ERROR) << "fcntl failure."; |
285 } | 279 } |
286 } | 280 } |
287 } | 281 } |
288 | 282 |
289 #if defined(OS_MACOSX) | |
290 | |
291 #define CHECK_MACH_ERROR(err, s) \ | |
292 do { \ | |
293 if (err != KERN_SUCCESS) { \ | |
294 fprintf(stderr, "%s 0x%x", s, (int)err); \ | |
295 exit(1); \ | |
296 } \ | |
297 } while (0) | |
298 | |
299 static int | |
300 setup_recv_port (mach_port_t *recv_port) | |
301 { | |
302 kern_return_t err; | |
303 mach_port_t port = MACH_PORT_NULL; | |
304 err = mach_port_allocate (mach_task_self (), | |
305 MACH_PORT_RIGHT_RECEIVE, &port); | |
306 CHECK_MACH_ERROR (err, "mach_port_allocate failed:"); | |
307 | |
308 err = mach_port_insert_right (mach_task_self (), | |
309 port, | |
310 port, | |
311 MACH_MSG_TYPE_MAKE_SEND); | |
312 CHECK_MACH_ERROR (err, "mach_port_insert_right failed:"); | |
313 | |
314 *recv_port = port; | |
315 return 0; | |
316 } | |
317 | |
318 static int | |
319 send_port (mach_port_t remote_port, mach_port_t port) | |
320 { | |
321 kern_return_t err; | |
322 | |
323 struct { | |
324 mach_msg_header_t header; | |
325 mach_msg_body_t body; | |
326 mach_msg_port_descriptor_t task_port; | |
327 } msg; | |
328 | |
329 msg.header.msgh_remote_port = remote_port; | |
330 msg.header.msgh_local_port = MACH_PORT_NULL; | |
331 msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0) | | |
332 MACH_MSGH_BITS_COMPLEX; | |
333 msg.header.msgh_size = sizeof msg; | |
334 | |
335 msg.body.msgh_descriptor_count = 1; | |
336 msg.task_port.name = port; | |
337 msg.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; | |
338 msg.task_port.type = MACH_MSG_PORT_DESCRIPTOR; | |
339 | |
340 err = mach_msg_send (&msg.header); | |
341 CHECK_MACH_ERROR (err, "mach_msg_send failed:"); | |
342 | |
343 return 0; | |
344 } | |
345 | |
346 static int | |
347 recv_port (mach_port_t recv_port, mach_port_t *port) | |
348 { | |
349 kern_return_t err; | |
350 struct { | |
351 mach_msg_header_t header; | |
352 mach_msg_body_t body; | |
353 mach_msg_port_descriptor_t task_port; | |
354 mach_msg_trailer_t trailer; | |
355 } msg; | |
356 | |
357 err = mach_msg (&msg.header, MACH_RCV_MSG, | |
358 0, sizeof msg, recv_port, | |
359 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | |
360 CHECK_MACH_ERROR (err, "mach_msg failed:"); | |
361 | |
362 *port = msg.task_port.name; | |
363 return 0; | |
364 } | |
365 | |
366 static task_t child_task = MACH_PORT_NULL; | |
367 | |
368 pid_t | |
369 sampling_fork () | |
370 { | |
371 kern_return_t err; | |
372 mach_port_t parent_recv_port = MACH_PORT_NULL; | |
373 mach_port_t child_recv_port = MACH_PORT_NULL; | |
374 | |
375 if (setup_recv_port (&parent_recv_port) != 0) | |
376 return -1; | |
377 err = task_set_bootstrap_port (mach_task_self (), parent_recv_port); | |
378 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
379 | |
380 pid_t pid; | |
381 switch (pid = fork ()) { | |
382 case -1: | |
383 err = mach_port_deallocate (mach_task_self(), parent_recv_port); | |
384 CHECK_MACH_ERROR (err, "mach_port_deallocate failed:"); | |
385 return pid; | |
386 case 0: /* child */ | |
387 err = task_get_bootstrap_port (mach_task_self (), &parent_recv_port); | |
388 CHECK_MACH_ERROR (err, "task_get_bootstrap_port failed:"); | |
389 if (setup_recv_port (&child_recv_port) != 0) | |
390 return -1; | |
391 if (send_port (parent_recv_port, mach_task_self ()) != 0) | |
392 return -1; | |
393 if (send_port (parent_recv_port, child_recv_port) != 0) | |
394 return -1; | |
395 if (recv_port (child_recv_port, &bootstrap_port) != 0) | |
396 return -1; | |
397 err = task_set_bootstrap_port (mach_task_self (), bootstrap_port); | |
398 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
399 break; | |
400 default: /* parent */ | |
401 err = task_set_bootstrap_port (mach_task_self (), bootstrap_port); | |
402 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
403 if (recv_port (parent_recv_port, &child_task) != 0) | |
404 return -1; | |
405 if (recv_port (parent_recv_port, &child_recv_port) != 0) | |
406 return -1; | |
407 if (send_port (child_recv_port, bootstrap_port) != 0) | |
408 return -1; | |
409 err = mach_port_deallocate (mach_task_self(), parent_recv_port); | |
410 CHECK_MACH_ERROR (err, "mach_port_deallocate failed:"); | |
411 break; | |
412 } | |
413 | |
414 return pid; | |
415 } | |
416 #endif | |
417 | |
418 bool LaunchApp(const std::vector<std::string>& argv, | 283 bool LaunchApp(const std::vector<std::string>& argv, |
419 const environment_vector& environ, | 284 const environment_vector& environ, |
420 const file_handle_mapping_vector& fds_to_remap, | 285 const file_handle_mapping_vector& fds_to_remap, |
421 bool wait, ProcessHandle* process_handle) { | 286 bool wait, ProcessHandle* process_handle) { |
422 #if defined(OS_MACOSX) | |
423 // Needs to be mutexed! :-( | |
424 pid_t pid = sampling_fork(); | |
425 MachBroker::instance()->RegisterPid( | |
426 pid, | |
427 MachBroker::MachInfo().SetTask(child_task)); | |
428 #else | |
429 pid_t pid = fork(); | 287 pid_t pid = fork(); |
430 #endif | |
431 if (pid < 0) | 288 if (pid < 0) |
432 return false; | 289 return false; |
433 | 290 |
434 if (pid == 0) { | 291 if (pid == 0) { |
435 // Child process | 292 // Child process |
436 #if defined(OS_MACOSX) | 293 #if defined(OS_MACOSX) |
437 RestoreDefaultExceptionHandler(); | 294 RestoreDefaultExceptionHandler(); |
438 #endif | 295 #endif |
439 | 296 |
440 InjectiveMultimap fd_shuffle; | 297 InjectiveMultimap fd_shuffle; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 const ProcessFilter* filter) { | 677 const ProcessFilter* filter) { |
821 bool exited_cleanly = | 678 bool exited_cleanly = |
822 WaitForProcessesToExit(executable_name, wait_milliseconds, | 679 WaitForProcessesToExit(executable_name, wait_milliseconds, |
823 filter); | 680 filter); |
824 if (!exited_cleanly) | 681 if (!exited_cleanly) |
825 KillProcesses(executable_name, exit_code, filter); | 682 KillProcesses(executable_name, exit_code, filter); |
826 return exited_cleanly; | 683 return exited_cleanly; |
827 } | 684 } |
828 | 685 |
829 } // namespace base | 686 } // namespace base |
OLD | NEW |