OLD | NEW |
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 "bin/process.h" | 5 #include "bin/process.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <signal.h> | 10 #include <signal.h> |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 int child_errno = errno; | 286 int child_errno = errno; |
287 char* os_error_message = strerror(errno); | 287 char* os_error_message = strerror(errno); |
288 ASSERT(sizeof(child_errno) == sizeof(errno)); | 288 ASSERT(sizeof(child_errno) == sizeof(errno)); |
289 int bytes_written = | 289 int bytes_written = |
290 FDUtils::WriteToBlocking( | 290 FDUtils::WriteToBlocking( |
291 exec_control_fd, &child_errno, sizeof(child_errno)); | 291 exec_control_fd, &child_errno, sizeof(child_errno)); |
292 if (bytes_written == sizeof(child_errno)) { | 292 if (bytes_written == sizeof(child_errno)) { |
293 FDUtils::WriteToBlocking( | 293 FDUtils::WriteToBlocking( |
294 exec_control_fd, os_error_message, strlen(os_error_message) + 1); | 294 exec_control_fd, os_error_message, strlen(os_error_message) + 1); |
295 } | 295 } |
296 TEMP_FAILURE_RETRY(close(exec_control_fd)); | 296 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd)); |
297 exit(1); | 297 exit(1); |
298 } | 298 } |
299 | 299 |
300 | 300 |
301 int Process::Start(const char* path, | 301 int Process::Start(const char* path, |
302 char* arguments[], | 302 char* arguments[], |
303 intptr_t arguments_length, | 303 intptr_t arguments_length, |
304 const char* working_directory, | 304 const char* working_directory, |
305 char* environment[], | 305 char* environment[], |
306 intptr_t environment_length, | 306 intptr_t environment_length, |
(...skipping 21 matching lines...) Expand all Loading... |
328 result = TEMP_FAILURE_RETRY(pipe(read_in)); | 328 result = TEMP_FAILURE_RETRY(pipe(read_in)); |
329 if (result < 0) { | 329 if (result < 0) { |
330 SetChildOsErrorMessage(os_error_message); | 330 SetChildOsErrorMessage(os_error_message); |
331 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 331 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
332 return errno; | 332 return errno; |
333 } | 333 } |
334 | 334 |
335 result = TEMP_FAILURE_RETRY(pipe(read_err)); | 335 result = TEMP_FAILURE_RETRY(pipe(read_err)); |
336 if (result < 0) { | 336 if (result < 0) { |
337 SetChildOsErrorMessage(os_error_message); | 337 SetChildOsErrorMessage(os_error_message); |
338 TEMP_FAILURE_RETRY(close(read_in[0])); | 338 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
339 TEMP_FAILURE_RETRY(close(read_in[1])); | 339 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
340 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 340 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
341 return errno; | 341 return errno; |
342 } | 342 } |
343 | 343 |
344 result = TEMP_FAILURE_RETRY(pipe(write_out)); | 344 result = TEMP_FAILURE_RETRY(pipe(write_out)); |
345 if (result < 0) { | 345 if (result < 0) { |
346 SetChildOsErrorMessage(os_error_message); | 346 SetChildOsErrorMessage(os_error_message); |
347 TEMP_FAILURE_RETRY(close(read_in[0])); | 347 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
348 TEMP_FAILURE_RETRY(close(read_in[1])); | 348 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
349 TEMP_FAILURE_RETRY(close(read_err[0])); | 349 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
350 TEMP_FAILURE_RETRY(close(read_err[1])); | 350 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
351 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 351 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
352 return errno; | 352 return errno; |
353 } | 353 } |
354 | 354 |
355 result = TEMP_FAILURE_RETRY(pipe(exec_control)); | 355 result = TEMP_FAILURE_RETRY(pipe(exec_control)); |
356 if (result < 0) { | 356 if (result < 0) { |
357 SetChildOsErrorMessage(os_error_message); | 357 SetChildOsErrorMessage(os_error_message); |
358 TEMP_FAILURE_RETRY(close(read_in[0])); | 358 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
359 TEMP_FAILURE_RETRY(close(read_in[1])); | 359 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
360 TEMP_FAILURE_RETRY(close(read_err[0])); | 360 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
361 TEMP_FAILURE_RETRY(close(read_err[1])); | 361 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
362 TEMP_FAILURE_RETRY(close(write_out[0])); | 362 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
363 TEMP_FAILURE_RETRY(close(write_out[1])); | 363 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
364 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 364 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
365 return errno; | 365 return errno; |
366 } | 366 } |
367 | 367 |
368 // Set close on exec on the write file descriptor of the exec control pipe. | 368 // Set close on exec on the write file descriptor of the exec control pipe. |
369 result = TEMP_FAILURE_RETRY( | 369 result = TEMP_FAILURE_RETRY( |
370 fcntl(exec_control[1], | 370 fcntl(exec_control[1], |
371 F_SETFD, | 371 F_SETFD, |
372 TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC)); | 372 TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC)); |
373 if (result < 0) { | 373 if (result < 0) { |
374 SetChildOsErrorMessage(os_error_message); | 374 SetChildOsErrorMessage(os_error_message); |
375 TEMP_FAILURE_RETRY(close(read_in[0])); | 375 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
376 TEMP_FAILURE_RETRY(close(read_in[1])); | 376 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
377 TEMP_FAILURE_RETRY(close(read_err[0])); | 377 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
378 TEMP_FAILURE_RETRY(close(read_err[1])); | 378 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
379 TEMP_FAILURE_RETRY(close(write_out[0])); | 379 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
380 TEMP_FAILURE_RETRY(close(write_out[1])); | 380 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
381 TEMP_FAILURE_RETRY(close(exec_control[0])); | 381 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
382 TEMP_FAILURE_RETRY(close(exec_control[1])); | 382 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
383 Log::PrintErr("fcntl failed: %s\n", *os_error_message); | 383 Log::PrintErr("fcntl failed: %s\n", *os_error_message); |
384 return errno; | 384 return errno; |
385 } | 385 } |
386 | 386 |
387 char** program_arguments = new char*[arguments_length + 2]; | 387 char** program_arguments = new char*[arguments_length + 2]; |
388 program_arguments[0] = const_cast<char*>(path); | 388 program_arguments[0] = const_cast<char*>(path); |
389 for (int i = 0; i < arguments_length; i++) { | 389 for (int i = 0; i < arguments_length; i++) { |
390 program_arguments[i + 1] = arguments[i]; | 390 program_arguments[i + 1] = arguments[i]; |
391 } | 391 } |
392 program_arguments[arguments_length + 1] = NULL; | 392 program_arguments[arguments_length + 1] = NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
404 bzero(&act, sizeof(act)); | 404 bzero(&act, sizeof(act)); |
405 act.sa_sigaction = SigChldHandler; | 405 act.sa_sigaction = SigChldHandler; |
406 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; | 406 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; |
407 if (sigaction(SIGCHLD, &act, 0) != 0) { | 407 if (sigaction(SIGCHLD, &act, 0) != 0) { |
408 perror("Process start: setting signal handler failed"); | 408 perror("Process start: setting signal handler failed"); |
409 } | 409 } |
410 pid = TEMP_FAILURE_RETRY(fork()); | 410 pid = TEMP_FAILURE_RETRY(fork()); |
411 if (pid < 0) { | 411 if (pid < 0) { |
412 SetChildOsErrorMessage(os_error_message); | 412 SetChildOsErrorMessage(os_error_message); |
413 delete[] program_arguments; | 413 delete[] program_arguments; |
414 TEMP_FAILURE_RETRY(close(read_in[0])); | 414 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
415 TEMP_FAILURE_RETRY(close(read_in[1])); | 415 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
416 TEMP_FAILURE_RETRY(close(read_err[0])); | 416 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
417 TEMP_FAILURE_RETRY(close(read_err[1])); | 417 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
418 TEMP_FAILURE_RETRY(close(write_out[0])); | 418 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
419 TEMP_FAILURE_RETRY(close(write_out[1])); | 419 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
420 TEMP_FAILURE_RETRY(close(exec_control[0])); | 420 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
421 TEMP_FAILURE_RETRY(close(exec_control[1])); | 421 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
422 return errno; | 422 return errno; |
423 } else if (pid == 0) { | 423 } else if (pid == 0) { |
424 // Wait for parent process before setting up the child process. | 424 // Wait for parent process before setting up the child process. |
425 char msg; | 425 char msg; |
426 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); | 426 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); |
427 if (bytes_read != sizeof(msg)) { | 427 if (bytes_read != sizeof(msg)) { |
428 perror("Failed receiving notification message"); | 428 perror("Failed receiving notification message"); |
429 exit(1); | 429 exit(1); |
430 } | 430 } |
431 | 431 |
432 TEMP_FAILURE_RETRY(close(write_out[1])); | 432 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
433 TEMP_FAILURE_RETRY(close(read_in[0])); | 433 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
434 TEMP_FAILURE_RETRY(close(read_err[0])); | 434 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
435 TEMP_FAILURE_RETRY(close(exec_control[0])); | 435 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
436 | 436 |
437 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { | 437 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { |
438 ReportChildError(exec_control[1]); | 438 ReportChildError(exec_control[1]); |
439 } | 439 } |
440 TEMP_FAILURE_RETRY(close(write_out[0])); | 440 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
441 | 441 |
442 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { | 442 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { |
443 ReportChildError(exec_control[1]); | 443 ReportChildError(exec_control[1]); |
444 } | 444 } |
445 TEMP_FAILURE_RETRY(close(read_in[1])); | 445 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
446 | 446 |
447 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { | 447 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { |
448 ReportChildError(exec_control[1]); | 448 ReportChildError(exec_control[1]); |
449 } | 449 } |
450 TEMP_FAILURE_RETRY(close(read_err[1])); | 450 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
451 | 451 |
452 if (working_directory != NULL && | 452 if (working_directory != NULL && |
453 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { | 453 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { |
454 ReportChildError(exec_control[1]); | 454 ReportChildError(exec_control[1]); |
455 } | 455 } |
456 | 456 |
457 if (program_environment != NULL) { | 457 if (program_environment != NULL) { |
458 environ = program_environment; | 458 environ = program_environment; |
459 } | 459 } |
460 | 460 |
461 TEMP_FAILURE_RETRY( | 461 VOID_TEMP_FAILURE_RETRY( |
462 execvp(path, const_cast<char* const*>(program_arguments))); | 462 execvp(path, const_cast<char* const*>(program_arguments))); |
463 | 463 |
464 ReportChildError(exec_control[1]); | 464 ReportChildError(exec_control[1]); |
465 } | 465 } |
466 | 466 |
467 // The arguments and environment for the spawned process are not needed | 467 // The arguments and environment for the spawned process are not needed |
468 // any longer. | 468 // any longer. |
469 delete[] program_arguments; | 469 delete[] program_arguments; |
470 delete[] program_environment; | 470 delete[] program_environment; |
471 | 471 |
472 int event_fds[2]; | 472 int event_fds[2]; |
473 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 473 result = TEMP_FAILURE_RETRY(pipe(event_fds)); |
474 if (result < 0) { | 474 if (result < 0) { |
475 SetChildOsErrorMessage(os_error_message); | 475 SetChildOsErrorMessage(os_error_message); |
476 TEMP_FAILURE_RETRY(close(read_in[0])); | 476 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
477 TEMP_FAILURE_RETRY(close(read_in[1])); | 477 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
478 TEMP_FAILURE_RETRY(close(read_err[0])); | 478 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
479 TEMP_FAILURE_RETRY(close(read_err[1])); | 479 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
480 TEMP_FAILURE_RETRY(close(write_out[0])); | 480 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
481 TEMP_FAILURE_RETRY(close(write_out[1])); | 481 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
482 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 482 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
483 return errno; | 483 return errno; |
484 } | 484 } |
485 FDUtils::SetCloseOnExec(event_fds[0]); | 485 FDUtils::SetCloseOnExec(event_fds[0]); |
486 FDUtils::SetCloseOnExec(event_fds[1]); | 486 FDUtils::SetCloseOnExec(event_fds[1]); |
487 | 487 |
488 ProcessInfoList::AddProcess(pid, event_fds[1]); | 488 ProcessInfoList::AddProcess(pid, event_fds[1]); |
489 *exit_event = event_fds[0]; | 489 *exit_event = event_fds[0]; |
490 FDUtils::SetNonBlocking(event_fds[0]); | 490 FDUtils::SetNonBlocking(event_fds[0]); |
491 | 491 |
492 // Notify child process to start. | 492 // Notify child process to start. |
493 char msg = '1'; | 493 char msg = '1'; |
494 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); | 494 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); |
495 if (result != sizeof(msg)) { | 495 if (result != sizeof(msg)) { |
496 perror("Failed sending notification message"); | 496 perror("Failed sending notification message"); |
497 } | 497 } |
498 | 498 |
499 // Read exec result from child. If no data is returned the exec was | 499 // Read exec result from child. If no data is returned the exec was |
500 // successful and the exec call closed the pipe. Otherwise the errno | 500 // successful and the exec call closed the pipe. Otherwise the errno |
501 // is written to the pipe. | 501 // is written to the pipe. |
502 TEMP_FAILURE_RETRY(close(exec_control[1])); | 502 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
503 int child_errno; | 503 int child_errno; |
504 int bytes_read = -1; | 504 int bytes_read = -1; |
505 ASSERT(sizeof(child_errno) == sizeof(errno)); | 505 ASSERT(sizeof(child_errno) == sizeof(errno)); |
506 bytes_read = | 506 bytes_read = |
507 FDUtils::ReadFromBlocking( | 507 FDUtils::ReadFromBlocking( |
508 exec_control[0], &child_errno, sizeof(child_errno)); | 508 exec_control[0], &child_errno, sizeof(child_errno)); |
509 if (bytes_read == sizeof(child_errno)) { | 509 if (bytes_read == sizeof(child_errno)) { |
510 static const int kMaxMessageSize = 256; | 510 static const int kMaxMessageSize = 256; |
511 char* message = static_cast<char*>(malloc(kMaxMessageSize)); | 511 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
512 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], | 512 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], |
513 message, | 513 message, |
514 kMaxMessageSize); | 514 kMaxMessageSize); |
515 message[kMaxMessageSize - 1] = '\0'; | 515 message[kMaxMessageSize - 1] = '\0'; |
516 *os_error_message = message; | 516 *os_error_message = message; |
517 } | 517 } |
518 TEMP_FAILURE_RETRY(close(exec_control[0])); | 518 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
519 | 519 |
520 // Return error code if any failures. | 520 // Return error code if any failures. |
521 if (bytes_read != 0) { | 521 if (bytes_read != 0) { |
522 TEMP_FAILURE_RETRY(close(read_in[0])); | 522 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
523 TEMP_FAILURE_RETRY(close(read_in[1])); | 523 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
524 TEMP_FAILURE_RETRY(close(read_err[0])); | 524 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
525 TEMP_FAILURE_RETRY(close(read_err[1])); | 525 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
526 TEMP_FAILURE_RETRY(close(write_out[0])); | 526 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
527 TEMP_FAILURE_RETRY(close(write_out[1])); | 527 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
528 if (bytes_read == -1) { | 528 if (bytes_read == -1) { |
529 return errno; // Read failed. | 529 return errno; // Read failed. |
530 } else { | 530 } else { |
531 return child_errno; // Exec failed. | 531 return child_errno; // Exec failed. |
532 } | 532 } |
533 } | 533 } |
534 | 534 |
535 FDUtils::SetNonBlocking(read_in[0]); | 535 FDUtils::SetNonBlocking(read_in[0]); |
536 *in = read_in[0]; | 536 *in = read_in[0]; |
537 TEMP_FAILURE_RETRY(close(read_in[1])); | 537 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
538 FDUtils::SetNonBlocking(write_out[1]); | 538 FDUtils::SetNonBlocking(write_out[1]); |
539 *out = write_out[1]; | 539 *out = write_out[1]; |
540 TEMP_FAILURE_RETRY(close(write_out[0])); | 540 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
541 FDUtils::SetNonBlocking(read_err[0]); | 541 FDUtils::SetNonBlocking(read_err[0]); |
542 *err = read_err[0]; | 542 *err = read_err[0]; |
543 TEMP_FAILURE_RETRY(close(read_err[1])); | 543 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
544 | 544 |
545 *id = pid; | 545 *id = pid; |
546 return 0; | 546 return 0; |
547 } | 547 } |
548 | 548 |
549 | 549 |
550 bool Process::Kill(intptr_t id, int signal) { | 550 bool Process::Kill(intptr_t id, int signal) { |
551 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 551 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); |
552 } | 552 } |
553 | 553 |
554 | 554 |
555 void Process::TerminateExitCodeHandler() { | 555 void Process::TerminateExitCodeHandler() { |
556 ExitCodeHandler::TerminateExitCodeThread(); | 556 ExitCodeHandler::TerminateExitCodeThread(); |
557 } | 557 } |
558 | 558 |
559 | 559 |
560 intptr_t Process::CurrentProcessId() { | 560 intptr_t Process::CurrentProcessId() { |
561 return static_cast<intptr_t>(getpid()); | 561 return static_cast<intptr_t>(getpid()); |
562 } | 562 } |
OLD | NEW |