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> |
(...skipping 10 matching lines...) Expand all Loading... |
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 const int kMicrosecondsPerSecond = 1000000; | 29 const int kMicrosecondsPerSecond = 1000000; |
30 | 30 |
31 #if defined(OS_MACOSX) | |
32 | |
33 std::map<pid_t, task_t> g_map; | |
34 | |
35 task_t foobar(pid_t pid) { | |
36 return g_map[pid]; | |
37 } | |
38 #endif | |
39 | |
40 | |
41 | |
42 namespace base { | 31 namespace base { |
43 | 32 |
44 namespace { | 33 namespace { |
45 | 34 |
46 int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, | 35 int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds, |
47 bool* success) { | 36 bool* success) { |
48 // 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 |
49 // 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 |
50 // exit sometime before the timeout has ended but we may still block for | 39 // exit sometime before the timeout has ended but we may still block for |
51 // up to 0.25 seconds after the fact. | 40 // up to 0.25 seconds after the fact. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 if (i <= STDERR_FILENO) | 273 if (i <= STDERR_FILENO) |
285 continue; | 274 continue; |
286 | 275 |
287 int flags = fcntl(i, F_GETFD); | 276 int flags = fcntl(i, F_GETFD); |
288 if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { | 277 if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { |
289 DLOG(ERROR) << "fcntl failure."; | 278 DLOG(ERROR) << "fcntl failure."; |
290 } | 279 } |
291 } | 280 } |
292 } | 281 } |
293 | 282 |
294 #if defined(OS_MACOSX) | |
295 | |
296 #define CHECK_MACH_ERROR(err, s) \ | |
297 do { \ | |
298 if (err != KERN_SUCCESS) { \ | |
299 fprintf(stderr, "%s 0x%x", s, (int)err); \ | |
300 exit(1); \ | |
301 } \ | |
302 } while (0) | |
303 | |
304 static int | |
305 setup_recv_port (mach_port_t *recv_port) | |
306 { | |
307 kern_return_t err; | |
308 mach_port_t port = MACH_PORT_NULL; | |
309 err = mach_port_allocate (mach_task_self (), | |
310 MACH_PORT_RIGHT_RECEIVE, &port); | |
311 CHECK_MACH_ERROR (err, "mach_port_allocate failed:"); | |
312 | |
313 err = mach_port_insert_right (mach_task_self (), | |
314 port, | |
315 port, | |
316 MACH_MSG_TYPE_MAKE_SEND); | |
317 CHECK_MACH_ERROR (err, "mach_port_insert_right failed:"); | |
318 | |
319 *recv_port = port; | |
320 return 0; | |
321 } | |
322 | |
323 static int | |
324 send_port (mach_port_t remote_port, mach_port_t port) | |
325 { | |
326 kern_return_t err; | |
327 | |
328 struct { | |
329 mach_msg_header_t header; | |
330 mach_msg_body_t body; | |
331 mach_msg_port_descriptor_t task_port; | |
332 } msg; | |
333 | |
334 msg.header.msgh_remote_port = remote_port; | |
335 msg.header.msgh_local_port = MACH_PORT_NULL; | |
336 msg.header.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0) | | |
337 MACH_MSGH_BITS_COMPLEX; | |
338 msg.header.msgh_size = sizeof msg; | |
339 | |
340 msg.body.msgh_descriptor_count = 1; | |
341 msg.task_port.name = port; | |
342 msg.task_port.disposition = MACH_MSG_TYPE_COPY_SEND; | |
343 msg.task_port.type = MACH_MSG_PORT_DESCRIPTOR; | |
344 | |
345 err = mach_msg_send (&msg.header); | |
346 CHECK_MACH_ERROR (err, "mach_msg_send failed:"); | |
347 | |
348 return 0; | |
349 } | |
350 | |
351 static int | |
352 recv_port (mach_port_t recv_port, mach_port_t *port) | |
353 { | |
354 kern_return_t err; | |
355 struct { | |
356 mach_msg_header_t header; | |
357 mach_msg_body_t body; | |
358 mach_msg_port_descriptor_t task_port; | |
359 mach_msg_trailer_t trailer; | |
360 } msg; | |
361 | |
362 err = mach_msg (&msg.header, MACH_RCV_MSG, | |
363 0, sizeof msg, recv_port, | |
364 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | |
365 CHECK_MACH_ERROR (err, "mach_msg failed:"); | |
366 | |
367 *port = msg.task_port.name; | |
368 return 0; | |
369 } | |
370 | |
371 static task_t child_task = MACH_PORT_NULL; | |
372 | |
373 pid_t | |
374 sampling_fork () | |
375 { | |
376 kern_return_t err; | |
377 mach_port_t parent_recv_port = MACH_PORT_NULL; | |
378 mach_port_t child_recv_port = MACH_PORT_NULL; | |
379 | |
380 if (setup_recv_port (&parent_recv_port) != 0) | |
381 return -1; | |
382 err = task_set_bootstrap_port (mach_task_self (), parent_recv_port); | |
383 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
384 | |
385 pid_t pid; | |
386 switch (pid = fork ()) { | |
387 case -1: | |
388 err = mach_port_deallocate (mach_task_self(), parent_recv_port); | |
389 CHECK_MACH_ERROR (err, "mach_port_deallocate failed:"); | |
390 return pid; | |
391 case 0: /* child */ | |
392 err = task_get_bootstrap_port (mach_task_self (), &parent_recv_port); | |
393 CHECK_MACH_ERROR (err, "task_get_bootstrap_port failed:"); | |
394 if (setup_recv_port (&child_recv_port) != 0) | |
395 return -1; | |
396 if (send_port (parent_recv_port, mach_task_self ()) != 0) | |
397 return -1; | |
398 if (send_port (parent_recv_port, child_recv_port) != 0) | |
399 return -1; | |
400 if (recv_port (child_recv_port, &bootstrap_port) != 0) | |
401 return -1; | |
402 err = task_set_bootstrap_port (mach_task_self (), bootstrap_port); | |
403 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
404 break; | |
405 default: /* parent */ | |
406 err = task_set_bootstrap_port (mach_task_self (), bootstrap_port); | |
407 CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:"); | |
408 if (recv_port (parent_recv_port, &child_task) != 0) | |
409 return -1; | |
410 if (recv_port (parent_recv_port, &child_recv_port) != 0) | |
411 return -1; | |
412 if (send_port (child_recv_port, bootstrap_port) != 0) | |
413 return -1; | |
414 err = mach_port_deallocate (mach_task_self(), parent_recv_port); | |
415 CHECK_MACH_ERROR (err, "mach_port_deallocate failed:"); | |
416 break; | |
417 } | |
418 | |
419 return pid; | |
420 } | |
421 #endif | |
422 | |
423 bool LaunchApp(const std::vector<std::string>& argv, | 283 bool LaunchApp(const std::vector<std::string>& argv, |
424 const environment_vector& environ, | 284 const environment_vector& environ, |
425 const file_handle_mapping_vector& fds_to_remap, | 285 const file_handle_mapping_vector& fds_to_remap, |
426 bool wait, ProcessHandle* process_handle) { | 286 bool wait, ProcessHandle* process_handle) { |
427 #if defined(OS_MACOSX) | |
428 // Needs to be mutexed! :-( | |
429 pid_t pid = sampling_fork(); | |
430 g_map[pid] = child_task; | |
431 #else | |
432 pid_t pid = fork(); | 287 pid_t pid = fork(); |
433 #endif | |
434 if (pid < 0) | 288 if (pid < 0) |
435 return false; | 289 return false; |
436 | 290 |
437 if (pid == 0) { | 291 if (pid == 0) { |
438 // Child process | 292 // Child process |
439 #if defined(OS_MACOSX) | 293 #if defined(OS_MACOSX) |
440 RestoreDefaultExceptionHandler(); | 294 RestoreDefaultExceptionHandler(); |
441 #endif | 295 #endif |
442 | 296 |
443 InjectiveMultimap fd_shuffle; | 297 InjectiveMultimap fd_shuffle; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 const ProcessFilter* filter) { | 677 const ProcessFilter* filter) { |
824 bool exited_cleanly = | 678 bool exited_cleanly = |
825 WaitForProcessesToExit(executable_name, wait_milliseconds, | 679 WaitForProcessesToExit(executable_name, wait_milliseconds, |
826 filter); | 680 filter); |
827 if (!exited_cleanly) | 681 if (!exited_cleanly) |
828 KillProcesses(executable_name, exit_code, filter); | 682 KillProcesses(executable_name, exit_code, filter); |
829 return exited_cleanly; | 683 return exited_cleanly; |
830 } | 684 } |
831 | 685 |
832 } // namespace base | 686 } // namespace base |
OLD | NEW |