Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1406)

Side by Side Diff: runtime/bin/process_macos.cc

Issue 798743004: Add support for starting a detached process (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_MACOS) 6 #if defined(TARGET_OS_MACOS)
7 7
8 #include "bin/process.h" 8 #include "bin/process.h"
9 9
10 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 exec_control_fd, &child_errno, sizeof(child_errno)); 251 exec_control_fd, &child_errno, sizeof(child_errno));
252 if (bytes_written == sizeof(child_errno)) { 252 if (bytes_written == sizeof(child_errno)) {
253 FDUtils::WriteToBlocking( 253 FDUtils::WriteToBlocking(
254 exec_control_fd, os_error_message, strlen(os_error_message) + 1); 254 exec_control_fd, os_error_message, strlen(os_error_message) + 1);
255 } 255 }
256 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd)); 256 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd));
257 exit(1); 257 exit(1);
258 } 258 }
259 259
260 260
261 static void ReportPid(int exec_control_fd, int pid) {
262 // In the case of starting a detached process the actual pid of that process
263 // is communicated using the exec control pipe.
264 int bytes_written =
265 FDUtils::WriteToBlocking(exec_control_fd, &pid, sizeof(pid));
266 ASSERT(bytes_written == sizeof(int));
267 USE(bytes_written);
268 }
269
270
271 static void ReadChildError(int exec_control_fd, char** error_message) {
272 const int kMaxMessageSize = 256;
273 char* message = static_cast<char*>(malloc(kMaxMessageSize));
274 if (message != NULL) {
275 FDUtils::ReadFromBlocking(exec_control_fd, message, kMaxMessageSize);
276 message[kMaxMessageSize - 1] = '\0';
277 *error_message = message;
278 } else {
279 static const char* no_message = "Cannot get error message, out of memory";
280 *error_message = const_cast<char*>(no_message);
281 }
282 }
283
284
261 int Process::Start(const char* path, 285 int Process::Start(const char* path,
262 char* arguments[], 286 char* arguments[],
263 intptr_t arguments_length, 287 intptr_t arguments_length,
264 const char* working_directory, 288 const char* working_directory,
265 char* environment[], 289 char* environment[],
266 intptr_t environment_length, 290 intptr_t environment_length,
291 bool detach,
267 intptr_t* in, 292 intptr_t* in,
268 intptr_t* out, 293 intptr_t* out,
269 intptr_t* err, 294 intptr_t* err,
270 intptr_t* id, 295 intptr_t* id,
271 intptr_t* exit_event, 296 intptr_t* exit_event,
272 char** os_error_message) { 297 char** os_error_message) {
273 pid_t pid; 298 pid_t pid;
274 int read_in[2]; // Pipe for stdout to child process. 299 int read_in[2] = {-1, -1}; // Pipe for stdout to child process.
275 int read_err[2]; // Pipe for stderr to child process. 300 int read_err[2] = {-1, -1}; // Pipe for stderr to child process.
276 int write_out[2]; // Pipe for stdin to child process. 301 int write_out[2] = {-1, -1}; // Pipe for stdin to child process.
277 int exec_control[2]; // Pipe to get the result from exec. 302 int exec_control[2] = {-1, -1}; // Pipe to get the result from exec.
278 int result; 303 int result;
279 304
280 result = TEMP_FAILURE_RETRY(pipe(read_in));
281 if (result < 0) {
282 SetChildOsErrorMessage(os_error_message);
283 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
284 return errno;
285 }
286 FDUtils::SetCloseOnExec(read_in[0]);
287
288 result = TEMP_FAILURE_RETRY(pipe(read_err));
289 if (result < 0) {
290 SetChildOsErrorMessage(os_error_message);
291 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
292 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
293 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
294 return errno;
295 }
296 FDUtils::SetCloseOnExec(read_err[0]);
297
298 result = TEMP_FAILURE_RETRY(pipe(write_out));
299 if (result < 0) {
300 SetChildOsErrorMessage(os_error_message);
301 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
302 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
303 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
304 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
305 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
306 return errno;
307 }
308 FDUtils::SetCloseOnExec(write_out[1]);
309
310 result = TEMP_FAILURE_RETRY(pipe(exec_control)); 305 result = TEMP_FAILURE_RETRY(pipe(exec_control));
311 if (result < 0) { 306 if (result < 0) {
312 SetChildOsErrorMessage(os_error_message); 307 SetChildOsErrorMessage(os_error_message);
313 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
314 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
315 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
316 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
317 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
318 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
319 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); 308 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
320 return errno; 309 return errno;
321 } 310 }
322 FDUtils::SetCloseOnExec(exec_control[0]); 311 FDUtils::SetCloseOnExec(exec_control[0]);
323 FDUtils::SetCloseOnExec(exec_control[1]); 312 FDUtils::SetCloseOnExec(exec_control[1]);
324 313
314 // For a detached process the pipe to connect stdout is still used for
315 // signaling when to do the first fork.
316 result = TEMP_FAILURE_RETRY(pipe(read_in));
325 if (result < 0) { 317 if (result < 0) {
326 SetChildOsErrorMessage(os_error_message); 318 SetChildOsErrorMessage(os_error_message);
327 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
328 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
329 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
330 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
331 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
332 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
333 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 319 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
334 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 320 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
335 Log::PrintErr("fcntl failed: %s\n", *os_error_message); 321 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
336 return errno; 322 return errno;
337 } 323 }
324 FDUtils::SetCloseOnExec(read_in[0]);
325
326 // For detached processes the pipe to connect stderr and stdin are not used.
327 if (!detach) {
328 result = TEMP_FAILURE_RETRY(pipe(read_err));
329 if (result < 0) {
330 SetChildOsErrorMessage(os_error_message);
331 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
332 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
333 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
334 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
335 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
336 return errno;
337 }
338 FDUtils::SetCloseOnExec(read_err[0]);
339
340 result = TEMP_FAILURE_RETRY(pipe(write_out));
341 if (result < 0) {
342 SetChildOsErrorMessage(os_error_message);
343 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
344 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
345 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
346 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
347 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
348 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
349 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
350 return errno;
351 }
352 FDUtils::SetCloseOnExec(write_out[1]);
353 }
338 354
339 char** program_arguments = new char*[arguments_length + 2]; 355 char** program_arguments = new char*[arguments_length + 2];
340 program_arguments[0] = const_cast<char*>(path); 356 program_arguments[0] = const_cast<char*>(path);
341 for (int i = 0; i < arguments_length; i++) { 357 for (int i = 0; i < arguments_length; i++) {
342 program_arguments[i + 1] = arguments[i]; 358 program_arguments[i + 1] = arguments[i];
343 } 359 }
344 program_arguments[arguments_length + 1] = NULL; 360 program_arguments[arguments_length + 1] = NULL;
345 361
346 char** program_environment = NULL; 362 char** program_environment = NULL;
347 if (environment != NULL) { 363 if (environment != NULL) {
348 program_environment = new char*[environment_length + 1]; 364 program_environment = new char*[environment_length + 1];
349 for (int i = 0; i < environment_length; i++) { 365 for (int i = 0; i < environment_length; i++) {
350 program_environment[i] = environment[i]; 366 program_environment[i] = environment[i];
351 } 367 }
352 program_environment[environment_length] = NULL; 368 program_environment[environment_length] = NULL;
353 } 369 }
354 370
355 pid = TEMP_FAILURE_RETRY(fork()); 371 pid = TEMP_FAILURE_RETRY(fork());
356 if (pid < 0) { 372 if (pid < 0) {
357 SetChildOsErrorMessage(os_error_message); 373 SetChildOsErrorMessage(os_error_message);
358 delete[] program_arguments; 374 delete[] program_arguments;
375 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
376 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
359 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 377 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
360 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 378 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
361 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 379 if (detach) {
362 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 380 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
363 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 381 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
364 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 382 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
365 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 383 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
366 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 384 }
367 return errno; 385 return errno;
368 } else if (pid == 0) { 386 } else if (pid == 0) {
369 // Wait for parent process before setting up the child process. 387 // Wait for parent process before setting up the child process.
370 char msg; 388 char msg;
371 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); 389 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg));
372 if (bytes_read != sizeof(msg)) { 390 if (bytes_read != sizeof(msg)) {
373 perror("Failed receiving notification message"); 391 perror("Failed receiving notification message");
374 exit(1); 392 exit(1);
375 } 393 }
394 if (detach) {
395 // For a detached process the pipe to connect stdout is only used for
396 // signaling when to do the first fork.
397 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
398 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
399 // Fork once more to start a new session.
400 pid = TEMP_FAILURE_RETRY(fork());
401 if (pid < 0) {
402 ReportChildError(exec_control[1]);
403 } else if (pid == 0) {
404 // Start a new session.
405 if (TEMP_FAILURE_RETRY(setsid()) == -1) {
406 ReportChildError(exec_control[1]);
407 } else {
408 // Do a final fork to not be the session leader.
409 pid = TEMP_FAILURE_RETRY(fork());
410 if (pid < 0) {
411 ReportChildError(exec_control[1]);
412 } else if (pid == 0) {
413 // Close all open file descriptors except for exec_control[1].
414 int max_fds = sysconf(_SC_OPEN_MAX);
415 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
416 for (int fd = 0; fd < max_fds; fd++) {
417 if (fd != exec_control[1]) {
418 VOID_TEMP_FAILURE_RETRY(close(fd));
419 }
420 }
376 421
377 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 422 // Re-open stdin, stdout and stderr and connect them to /dev/null.
378 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 423 // The loop above should already have closed all of them, so
379 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 424 // creating new file descriptors should start at STDIN_FILENO.
380 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 425 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
426 if (fd != STDIN_FILENO) {
427 ReportChildError(exec_control[1]);
428 }
429 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
430 STDOUT_FILENO) {
431 ReportChildError(exec_control[1]);
432 }
433 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
434 STDERR_FILENO) {
435 ReportChildError(exec_control[1]);
436 }
381 437
382 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { 438 // Report the final PID and do the exec.
439 ReportPid(exec_control[1], getpid()); // getpid cannot fail.
440 VOID_TEMP_FAILURE_RETRY(
441 execvp(path, const_cast<char* const*>(program_arguments)));
442 ReportChildError(exec_control[1]);
443 } else {
444 exit(0);
445 }
446 }
447 } else {
448 exit(0);
449 }
450 } else {
451 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
452 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
453 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
454 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
455
456 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
457 ReportChildError(exec_control[1]);
458 }
459 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
460
461 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
462 ReportChildError(exec_control[1]);
463 }
464 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
465
466 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
467 ReportChildError(exec_control[1]);
468 }
469 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
470
471 if (working_directory != NULL &&
472 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
473 ReportChildError(exec_control[1]);
474 }
475
476 if (program_environment != NULL) {
477 environ = program_environment;
478 }
479
480 VOID_TEMP_FAILURE_RETRY(
481 execvp(path, const_cast<char* const*>(program_arguments)));
482
383 ReportChildError(exec_control[1]); 483 ReportChildError(exec_control[1]);
384 } 484 }
385 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
386
387 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
388 ReportChildError(exec_control[1]);
389 }
390 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
391
392 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
393 ReportChildError(exec_control[1]);
394 }
395 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
396
397 if (working_directory != NULL &&
398 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) {
399 ReportChildError(exec_control[1]);
400 }
401
402 if (program_environment != NULL) {
403 environ = program_environment;
404 }
405
406 VOID_TEMP_FAILURE_RETRY(
407 execvp(path, const_cast<char* const*>(program_arguments)));
408
409 ReportChildError(exec_control[1]);
410 } 485 }
411 486
412 // Be sure to listen for exit-codes, now we have a child-process. 487 // Be sure to listen for exit-codes, now we have a child-process.
413 ExitCodeHandler::ProcessStarted(); 488 ExitCodeHandler::ProcessStarted();
414 489
415 // The arguments and environment for the spawned process are not needed 490 // The arguments and environment for the spawned process are not needed
416 // any longer. 491 // any longer.
417 delete[] program_arguments; 492 delete[] program_arguments;
418 delete[] program_environment; 493 delete[] program_environment;
419 494
420 int event_fds[2]; 495 if (!detach) {
421 result = TEMP_FAILURE_RETRY(pipe(event_fds)); 496 int event_fds[2];
422 if (result < 0) { 497 result = TEMP_FAILURE_RETRY(pipe(event_fds));
423 SetChildOsErrorMessage(os_error_message); 498 if (result < 0) {
424 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 499 SetChildOsErrorMessage(os_error_message);
425 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 500 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
426 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 501 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
427 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 502 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
428 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 503 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
429 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 504 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
430 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); 505 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
431 return errno; 506 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
507 return errno;
508 }
509 FDUtils::SetCloseOnExec(event_fds[0]);
510 FDUtils::SetCloseOnExec(event_fds[1]);
511
512 ProcessInfoList::AddProcess(pid, event_fds[1]);
513 *exit_event = event_fds[0];
514 FDUtils::SetNonBlocking(event_fds[0]);
432 } 515 }
433 FDUtils::SetCloseOnExec(event_fds[0]);
434 FDUtils::SetCloseOnExec(event_fds[1]);
435
436 ProcessInfoList::AddProcess(pid, event_fds[1]);
437 *exit_event = event_fds[0];
438 FDUtils::SetNonBlocking(event_fds[0]);
439 516
440 // Notify child process to start. 517 // Notify child process to start.
441 char msg = '1'; 518 char msg = '1';
442 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); 519 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg));
443 if (result != sizeof(msg)) { 520 if (result != sizeof(msg)) {
444 perror("Failed sending notification message"); 521 perror("Failed sending notification message");
445 } 522 }
446 523
447 // Read exec result from child. If no data is returned the exec was 524 // Read exec result from child. If no data is returned the exec was
448 // successful and the exec call closed the pipe. Otherwise the errno 525 // successful and the exec call closed the pipe. Otherwise the errno
449 // is written to the pipe. 526 // is written to the pipe.
450 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 527 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
528 bool failed = false;
451 int child_errno; 529 int child_errno;
452 int bytes_read = -1; 530 int bytes_read = -1;
453 ASSERT(sizeof(child_errno) == sizeof(errno)); 531 ASSERT(sizeof(child_errno) == sizeof(errno));
454 bytes_read = 532 if (!detach) {
455 FDUtils::ReadFromBlocking( 533 // Read exec result from child. If no data is returned the exec was
456 exec_control[0], &child_errno, sizeof(child_errno)); 534 // successful and the exec call closed the pipe. Otherwise the errno
457 if (bytes_read == sizeof(child_errno)) { 535 // is written to the pipe.
458 static const int kMaxMessageSize = 256; 536 bytes_read =
459 char* message = static_cast<char*>(malloc(kMaxMessageSize)); 537 FDUtils::ReadFromBlocking(
460 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], 538 exec_control[0], &child_errno, sizeof(child_errno));
461 message, 539 if (bytes_read == sizeof(child_errno)) {
462 kMaxMessageSize); 540 ReadChildError(exec_control[0], os_error_message);
463 message[kMaxMessageSize - 1] = '\0'; 541 failed = true;
464 *os_error_message = message; 542 }
543 } else {
544 // Read exec result from child. If only pid data is returned the exec was
545 // successful and the exec call closed the pipe. Otherwise the errno
546 // is written to the pipe as well.
547 int result[2];
548 ASSERT(sizeof(int) == sizeof(child_errno));
549 bytes_read =
550 FDUtils::ReadFromBlocking(
551 exec_control[0], result, sizeof(result));
552 if (bytes_read == sizeof(int)) {
553 pid = result[0];
554 } else if (bytes_read == 2 * sizeof(int)) {
555 pid = result[0];
556 child_errno = result[1];
557 ReadChildError(exec_control[0], os_error_message);
558 failed = true;
559 }
465 } 560 }
466 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 561 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
467 562
468 // Return error code if any failures. 563 // Return error code if any failures.
469 if (bytes_read != 0) { 564 if (failed) {
470 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 565 if (!detach) {
471 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 566 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
472 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 567 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
473 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 568 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
474 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 569 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
475 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 570 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
571 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
476 572
477 // Since exec() failed, we're not interested in the exit code. 573 // Since exec() failed, we're not interested in the exit code.
478 // We close the reading side of the exit code pipe here. 574 // We close the reading side of the exit code pipe here.
479 // GetProcessExitCodes will get a broken pipe error when it tries to write 575 // GetProcessExitCodes will get a broken pipe error when it tries to write
480 // to the writing side of the pipe and it will ignore the error. 576 // to the writing side of the pipe and it will ignore the error.
481 VOID_TEMP_FAILURE_RETRY(close(*exit_event)); 577 VOID_TEMP_FAILURE_RETRY(close(*exit_event));
482 *exit_event = -1; 578 *exit_event = -1;
483 579 }
484 if (bytes_read == -1) { 580 if (bytes_read == -1) {
485 return errno; // Read failed. 581 return errno; // Read failed.
486 } else { 582 } else {
487 return child_errno; // Exec failed. 583 return child_errno; // Exec failed.
488 } 584 }
489 } 585 }
490 586
491 FDUtils::SetNonBlocking(read_in[0]); 587 FDUtils::SetNonBlocking(read_in[0]);
492 *in = read_in[0]; 588 *in = read_in[0];
493 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 589 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 bzero(&act, sizeof(act)); 885 bzero(&act, sizeof(act));
790 act.sa_handler = SIG_DFL; 886 act.sa_handler = SIG_DFL;
791 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); 887 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL));
792 } 888 }
793 } 889 }
794 890
795 } // namespace bin 891 } // namespace bin
796 } // namespace dart 892 } // namespace dart
797 893
798 #endif // defined(TARGET_OS_MACOS) 894 #endif // defined(TARGET_OS_MACOS)
OLDNEW
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698