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

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

Issue 798743004: Add support for starting a detached process (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fixes + rebase 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
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_LINUX) 6 #if defined(TARGET_OS_LINUX)
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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 exec_control_fd, &child_errno, sizeof(child_errno)); 249 exec_control_fd, &child_errno, sizeof(child_errno));
250 if (bytes_written == sizeof(child_errno)) { 250 if (bytes_written == sizeof(child_errno)) {
251 FDUtils::WriteToBlocking( 251 FDUtils::WriteToBlocking(
252 exec_control_fd, os_error_message, strlen(os_error_message) + 1); 252 exec_control_fd, os_error_message, strlen(os_error_message) + 1);
253 } 253 }
254 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd)); 254 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd));
255 exit(1); 255 exit(1);
256 } 256 }
257 257
258 258
259 static void ReportPid(int exec_control_fd, int pid) {
260 // In the case of starting a detached process the actual pid of that process
261 // is communicated using the exec control pipe.
262 int bytes_written =
263 FDUtils::WriteToBlocking(
264 exec_control_fd, &pid, sizeof(pid));
kustermann 2015/01/16 16:11:03 doesn't this fit on the previous line?
Søren Gjesse 2015/01/21 12:32:34 Done.
265 ASSERT(bytes_written == sizeof(int));
266 USE(bytes_written);
267 }
268
269
259 int Process::Start(const char* path, 270 int Process::Start(const char* path,
260 char* arguments[], 271 char* arguments[],
261 intptr_t arguments_length, 272 intptr_t arguments_length,
262 const char* working_directory, 273 const char* working_directory,
263 char* environment[], 274 char* environment[],
264 intptr_t environment_length, 275 intptr_t environment_length,
276 bool detached,
265 intptr_t* in, 277 intptr_t* in,
266 intptr_t* out, 278 intptr_t* out,
267 intptr_t* err, 279 intptr_t* err,
268 intptr_t* id, 280 intptr_t* id,
269 intptr_t* exit_event, 281 intptr_t* exit_event,
270 char** os_error_message) { 282 char** os_error_message) {
271 pid_t pid; 283 pid_t pid;
272 int read_in[2]; // Pipe for stdout to child process. 284 int read_in[2] = {-1, -1}; // Pipe for stdout to child process.
273 int read_err[2]; // Pipe for stderr to child process. 285 int read_err[2] = {-1, -1}; // Pipe for stderr to child process.
274 int write_out[2]; // Pipe for stdin to child process. 286 int write_out[2] = {-1, -1}; // Pipe for stdin to child process.
275 int exec_control[2]; // Pipe to get the result from exec. 287 int exec_control[2] = {-1, -1}; // Pipe to get the result from exec.
276 int result; 288 int result;
277 289
278 result = pipe(read_in);
279 if (result < 0) {
280 SetChildOsErrorMessage(os_error_message);
281 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
282 return errno;
283 }
284 FDUtils::SetCloseOnExec(read_in[0]);
285
286 result = pipe(read_err);
287 if (result < 0) {
288 SetChildOsErrorMessage(os_error_message);
289 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
290 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
291 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
292 return errno;
293 }
294 FDUtils::SetCloseOnExec(read_err[0]);
295
296 result = pipe(write_out);
297 if (result < 0) {
298 SetChildOsErrorMessage(os_error_message);
299 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
300 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
301 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
302 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
303 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
304 return errno;
305 }
306 FDUtils::SetCloseOnExec(write_out[1]);
307
308 result = pipe(exec_control); 290 result = pipe(exec_control);
309 if (result < 0) { 291 if (result < 0) {
310 SetChildOsErrorMessage(os_error_message); 292 SetChildOsErrorMessage(os_error_message);
311 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
312 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
313 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
314 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
315 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
316 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
317 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); 293 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
318 return errno; 294 return errno;
319 } 295 }
320 FDUtils::SetCloseOnExec(exec_control[0]); 296 FDUtils::SetCloseOnExec(exec_control[0]);
321 FDUtils::SetCloseOnExec(exec_control[1]); 297 FDUtils::SetCloseOnExec(exec_control[1]);
322 298
299 // For a detached process the pipe to connect stdout is still used for
300 // signaling when to do the first fork.
301 result = pipe(read_in);
323 if (result < 0) { 302 if (result < 0) {
324 SetChildOsErrorMessage(os_error_message); 303 SetChildOsErrorMessage(os_error_message);
325 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
326 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
327 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
328 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
329 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
330 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
331 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 304 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
332 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 305 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
333 Log::PrintErr("fcntl failed: %s\n", *os_error_message); 306 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
334 return errno; 307 return errno;
335 } 308 }
309 FDUtils::SetCloseOnExec(read_in[0]);
310
311 // For detached processes the pipe to connect stderr and stdin are not used.
312 if (!detached) {
313 result = pipe(read_err);
314 if (result < 0) {
315 SetChildOsErrorMessage(os_error_message);
316 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
317 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
318 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
319 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
320 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
321 return errno;
322 }
323 FDUtils::SetCloseOnExec(read_err[0]);
324
325 result = pipe(write_out);
326 if (result < 0) {
327 SetChildOsErrorMessage(os_error_message);
328 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
329 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
330 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
331 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
332 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
333 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
334 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
335 return errno;
336 }
337 FDUtils::SetCloseOnExec(write_out[1]);
338 }
336 339
337 char** program_arguments = new char*[arguments_length + 2]; 340 char** program_arguments = new char*[arguments_length + 2];
338 program_arguments[0] = const_cast<char*>(path); 341 program_arguments[0] = const_cast<char*>(path);
339 for (int i = 0; i < arguments_length; i++) { 342 for (int i = 0; i < arguments_length; i++) {
340 program_arguments[i + 1] = arguments[i]; 343 program_arguments[i + 1] = arguments[i];
341 } 344 }
342 program_arguments[arguments_length + 1] = NULL; 345 program_arguments[arguments_length + 1] = NULL;
343 346
344 char** program_environment = NULL; 347 char** program_environment = NULL;
345 if (environment != NULL) { 348 if (environment != NULL) {
346 program_environment = new char*[environment_length + 1]; 349 program_environment = new char*[environment_length + 1];
347 for (int i = 0; i < environment_length; i++) { 350 for (int i = 0; i < environment_length; i++) {
348 program_environment[i] = environment[i]; 351 program_environment[i] = environment[i];
349 } 352 }
350 program_environment[environment_length] = NULL; 353 program_environment[environment_length] = NULL;
351 } 354 }
352 355
353 pid = TEMP_FAILURE_RETRY(fork()); 356 pid = TEMP_FAILURE_RETRY(fork());
354 if (pid < 0) { 357 if (pid < 0) {
355 SetChildOsErrorMessage(os_error_message); 358 SetChildOsErrorMessage(os_error_message);
356 delete[] program_arguments; 359 delete[] program_arguments;
360 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
361 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
357 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 362 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
358 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 363 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
359 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 364 if (!detached) {
360 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 365 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
361 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 366 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
362 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 367 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
363 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 368 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
364 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 369 }
365 return errno; 370 return errno;
366 } else if (pid == 0) { 371 } else if (pid == 0) {
367 // Wait for parent process before setting up the child process. 372 // Wait for parent process before setting up the child process.
368 char msg; 373 char msg;
369 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); 374 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg));
370 if (bytes_read != sizeof(msg)) { 375 if (bytes_read != sizeof(msg)) {
371 perror("Failed receiving notification message"); 376 perror("Failed receiving notification message");
372 exit(1); 377 exit(1);
373 } 378 }
379 if (detached) {
380 // For a detached process the pipe to connect stdout is only used for
381 // signaling when to do the first fork.
382 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
383 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
384 // Fork once more to start a new session.
385 pid = TEMP_FAILURE_RETRY(fork());
386 if (pid < 0) {
387 ReportChildError(exec_control[1]);
388 } else if (pid == 0) {
389 // Start a new session.
390 if (TEMP_FAILURE_RETRY(setsid()) == -1) {
391 ReportChildError(exec_control[1]);
392 } else {
393 // Do a final fork to not be the session leader.
394 pid = TEMP_FAILURE_RETRY(fork());
395 if (pid < 0) {
396 ReportChildError(exec_control[1]);
397 } else if (pid == 0) {
398 // Close all open file descriptors except for exec_control[1].
399 int max_fds = sysconf(_SC_OPEN_MAX);
400 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
401 for (int fd = 0; fd < max_fds; fd++) {
402 if (fd != exec_control[1]) {
403 VOID_TEMP_FAILURE_RETRY(close(fd));
404 }
405 }
374 406
375 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 407 // Re-open stdin, stdout and stderr and connect them to /dev/null.
376 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 408 VOID_TEMP_FAILURE_RETRY(close(STDIN_FILENO));
kustermann 2015/01/16 16:11:03 That one should be included by the loop above.
Søren Gjesse 2015/01/21 12:32:35 Done, and added comment.
377 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 409 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
378 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 410 if (fd != STDIN_FILENO) {
411 ReportChildError(exec_control[1]);
412 }
413 if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) {
414 ReportChildError(exec_control[1]);
415 }
416 if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
417 ReportChildError(exec_control[1]);
418 }
379 419
380 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { 420 // Report the final PID and do the exec.
421 ReportPid(exec_control[1], getpid()); // getpid cannot fail.
422 execvp(path, const_cast<char* const*>(program_arguments));
423 ReportChildError(exec_control[1]);
424 } else {
425 exit(0);
426 }
427 }
428 } else {
429 exit(0);
430 }
431 } else {
432 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
433 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
434 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
435 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
436
437 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) {
438 ReportChildError(exec_control[1]);
439 }
440 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
441
442 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
443 ReportChildError(exec_control[1]);
444 }
445 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
446
447 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
448 ReportChildError(exec_control[1]);
449 }
450 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
451
452 if (working_directory != NULL && chdir(working_directory) == -1) {
453 ReportChildError(exec_control[1]);
454 }
455
456 if (program_environment != NULL) {
457 environ = program_environment;
458 }
459
460 execvp(path, const_cast<char* const*>(program_arguments));
461
381 ReportChildError(exec_control[1]); 462 ReportChildError(exec_control[1]);
382 } 463 }
383 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
384
385 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) {
386 ReportChildError(exec_control[1]);
387 }
388 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
389
390 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) {
391 ReportChildError(exec_control[1]);
392 }
393 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
394
395 if (working_directory != NULL && chdir(working_directory) == -1) {
396 ReportChildError(exec_control[1]);
397 }
398
399 if (program_environment != NULL) {
400 environ = program_environment;
401 }
402
403 execvp(path, const_cast<char* const*>(program_arguments));
404
405 ReportChildError(exec_control[1]);
406 } 464 }
407 465
408 // Be sure to listen for exit-codes, now we have a child-process. 466 // Be sure to listen for exit-codes, now we have a child-process.
409 ExitCodeHandler::ProcessStarted(); 467 ExitCodeHandler::ProcessStarted();
kustermann 2015/01/16 16:11:03 For detached processes this is not necessary. We'r
Søren Gjesse 2015/01/21 12:32:35 No, but we still need to call wait to avoid zombie
410 468
411 // The arguments and environment for the spawned process are not needed 469 // The arguments and environment for the spawned process are not needed
412 // any longer. 470 // any longer.
413 delete[] program_arguments; 471 delete[] program_arguments;
414 delete[] program_environment; 472 delete[] program_environment;
415 473
416 int event_fds[2]; 474 if (!detached) {
417 result = pipe(event_fds); 475 int event_fds[2];
418 if (result < 0) { 476 result = pipe(event_fds);
419 SetChildOsErrorMessage(os_error_message); 477 if (result < 0) {
420 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 478 SetChildOsErrorMessage(os_error_message);
421 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 479 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
422 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 480 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
423 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 481 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
424 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 482 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
425 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 483 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
426 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); 484 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
427 return errno; 485 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message);
486 return errno;
487 }
488 FDUtils::SetCloseOnExec(event_fds[0]);
489 FDUtils::SetCloseOnExec(event_fds[1]);
490
491 ProcessInfoList::AddProcess(pid, event_fds[1]);
492 *exit_event = event_fds[0];
493 FDUtils::SetNonBlocking(event_fds[0]);
428 } 494 }
429 FDUtils::SetCloseOnExec(event_fds[0]);
430 FDUtils::SetCloseOnExec(event_fds[1]);
431
432 ProcessInfoList::AddProcess(pid, event_fds[1]);
433 *exit_event = event_fds[0];
434 FDUtils::SetNonBlocking(event_fds[0]);
435 495
436 // Notify child process to start. 496 // Notify child process to start.
437 char msg = '1'; 497 char msg = '1';
438 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); 498 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg));
439 if (result != sizeof(msg)) { 499 if (result != sizeof(msg)) {
440 perror("Failed sending notification message"); 500 perror("Failed sending notification message");
441 } 501 }
442 502
443 // Read exec result from child. If no data is returned the exec was
444 // successful and the exec call closed the pipe. Otherwise the errno
445 // is written to the pipe.
446 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); 503 VOID_TEMP_FAILURE_RETRY(close(exec_control[1]));
504 bool failed = false;
447 int child_errno; 505 int child_errno;
448 int bytes_read = -1; 506 int bytes_read = -1;
449 ASSERT(sizeof(child_errno) == sizeof(errno)); 507 ASSERT(sizeof(child_errno) == sizeof(errno));
450 bytes_read = 508 if (!detached) {
451 FDUtils::ReadFromBlocking( 509 // Read exec result from child. If no data is returned the exec was
452 exec_control[0], &child_errno, sizeof(child_errno)); 510 // successful and the exec call closed the pipe. Otherwise the errno
453 if (bytes_read == sizeof(child_errno)) { 511 // is written to the pipe.
454 static const int kMaxMessageSize = 256; 512 bytes_read =
455 char* message = static_cast<char*>(malloc(kMaxMessageSize)); 513 FDUtils::ReadFromBlocking(
456 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], 514 exec_control[0], &child_errno, sizeof(child_errno));
457 message, 515 if (bytes_read == sizeof(child_errno)) {
458 kMaxMessageSize); 516 static const int kMaxMessageSize = 256;
459 message[kMaxMessageSize - 1] = '\0'; 517 char* message = static_cast<char*>(malloc(kMaxMessageSize));
kustermann 2015/01/16 16:11:03 The malloc() can potentially return NULL.
Søren Gjesse 2015/01/21 12:32:35 Added check and return a fixed error if malloc fai
460 *os_error_message = message; 518 bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
519 message,
520 kMaxMessageSize);
521 message[kMaxMessageSize - 1] = '\0';
522 *os_error_message = message;
523 failed = true;
524 }
525 } else {
526 // Read exec result from child. If only pid data is returned the exec was
527 // successful and the exec call closed the pipe. Otherwise the errno
528 // is written to the pipe as well.
529 int result[2];
530 ASSERT(sizeof(int) == sizeof(child_errno));
kustermann 2015/01/16 16:11:03 That is a tautology because child_errno is defined
Søren Gjesse 2015/01/21 12:32:35 Yes, it is mainly there to document the checks for
531 bytes_read =
532 FDUtils::ReadFromBlocking(
533 exec_control[0], result, sizeof(result));
534 if (bytes_read == sizeof(int)) {
535 pid = result[0];
536 } else if (bytes_read == 2 * sizeof(int)) {
537 pid = result[0];
538 child_errno = result[1];
539 static const int kMaxMessageSize = 256;
540 char* message = static_cast<char*>(malloc(kMaxMessageSize));
kustermann 2015/01/16 16:11:03 ditto.
Søren Gjesse 2015/01/21 12:32:35 ditto.
541 bytes_read = FDUtils::ReadFromBlocking(exec_control[0],
542 message,
543 kMaxMessageSize);
544 message[kMaxMessageSize - 1] = '\0';
545 *os_error_message = message;
546 failed = true;
547 }
461 } 548 }
462 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); 549 VOID_TEMP_FAILURE_RETRY(close(exec_control[0]));
463 550
464 // Return error code if any failures. 551 // Return error code if any failures.
465 if (bytes_read != 0) { 552 if (failed) {
466 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); 553 if (!detached) {
467 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 554 VOID_TEMP_FAILURE_RETRY(close(read_in[0]));
468 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); 555 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
469 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); 556 VOID_TEMP_FAILURE_RETRY(close(read_err[0]));
470 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); 557 VOID_TEMP_FAILURE_RETRY(close(read_err[1]));
471 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); 558 VOID_TEMP_FAILURE_RETRY(close(write_out[0]));
559 VOID_TEMP_FAILURE_RETRY(close(write_out[1]));
472 560
473 // Since exec() failed, we're not interested in the exit code. 561 // Since exec() failed, we're not interested in the exit code.
474 // We close the reading side of the exit code pipe here. 562 // We close the reading side of the exit code pipe here.
475 // GetProcessExitCodes will get a broken pipe error when it tries to write 563 // GetProcessExitCodes will get a broken pipe error when it tries to write
476 // to the writing side of the pipe and it will ignore the error. 564 // to the writing side of the pipe and it will ignore the error.
477 VOID_TEMP_FAILURE_RETRY(close(*exit_event)); 565 VOID_TEMP_FAILURE_RETRY(close(*exit_event));
478 *exit_event = -1; 566 *exit_event = -1;
479 567 }
480 if (bytes_read == -1) { 568 if (bytes_read == -1) {
481 return errno; // Read failed. 569 return errno; // Read failed.
482 } else { 570 } else {
483 return child_errno; // Exec failed. 571 return child_errno; // Exec failed.
484 } 572 }
485 } 573 }
486 574
487 FDUtils::SetNonBlocking(read_in[0]); 575 FDUtils::SetNonBlocking(read_in[0]);
488 *in = read_in[0]; 576 *in = read_in[0];
489 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); 577 VOID_TEMP_FAILURE_RETRY(close(read_in[1]));
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 bzero(&act, sizeof(act)); 822 bzero(&act, sizeof(act));
735 act.sa_handler = SIG_DFL; 823 act.sa_handler = SIG_DFL;
736 sigaction(signal, &act, NULL); 824 sigaction(signal, &act, NULL);
737 } 825 }
738 } 826 }
739 827
740 } // namespace bin 828 } // namespace bin
741 } // namespace dart 829 } // namespace dart
742 830
743 #endif // defined(TARGET_OS_LINUX) 831 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« no previous file with comments | « runtime/bin/process.cc ('k') | runtime/bin/process_patch.dart » ('j') | sdk/lib/io/process.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698