| 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 "platform/globals.h" | 5 #include "platform/globals.h" |
| 6 #if defined(TARGET_OS_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
| 7 | 7 |
| 8 #include "bin/process.h" | 8 #include "bin/process.h" |
| 9 | 9 |
| 10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
| 11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
| 12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
| 13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
| 14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
| 15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
| 16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
| 17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
| 18 | 18 |
| 19 #include "bin/fdutils.h" | 19 #include "bin/fdutils.h" |
| 20 #include "bin/log.h" | 20 #include "bin/log.h" |
| 21 #include "bin/signal_blocker.h" | |
| 22 #include "bin/thread.h" | 21 #include "bin/thread.h" |
| 23 | 22 |
| 23 #include "platform/signal_blocker.h" |
| 24 |
| 24 | 25 |
| 25 extern char **environ; | 26 extern char **environ; |
| 26 | 27 |
| 27 | 28 |
| 28 namespace dart { | 29 namespace dart { |
| 29 namespace bin { | 30 namespace bin { |
| 30 | 31 |
| 31 // ProcessInfo is used to map a process id to the file descriptor for | 32 // ProcessInfo is used to map a process id to the file descriptor for |
| 32 // the pipe used to communicate the exit code of the process to Dart. | 33 // the pipe used to communicate the exit code of the process to Dart. |
| 33 // ProcessInfo objects are kept in the static singly-linked | 34 // ProcessInfo objects are kept in the static singly-linked |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 | 145 |
| 145 if (!running_) { | 146 if (!running_) { |
| 146 return; | 147 return; |
| 147 } | 148 } |
| 148 | 149 |
| 149 // Set terminate_done_ to false, so we can use it as a guard for our | 150 // Set terminate_done_ to false, so we can use it as a guard for our |
| 150 // monitor. | 151 // monitor. |
| 151 running_ = false; | 152 running_ = false; |
| 152 | 153 |
| 153 // Fork to wake up waitpid. | 154 // Fork to wake up waitpid. |
| 154 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fork()) == 0) { | 155 if (TEMP_FAILURE_RETRY(fork()) == 0) { |
| 155 exit(0); | 156 exit(0); |
| 156 } | 157 } |
| 157 | 158 |
| 158 monitor_->Notify(); | 159 monitor_->Notify(); |
| 159 | 160 |
| 160 while (!terminate_done_) { | 161 while (!terminate_done_) { |
| 161 monitor_->Wait(dart::Monitor::kNoTimeout); | 162 monitor_->Wait(dart::Monitor::kNoTimeout); |
| 162 } | 163 } |
| 163 } | 164 } |
| 164 | 165 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 char os_error_message[kBufferSize]; | 245 char os_error_message[kBufferSize]; |
| 245 strerror_r(errno, os_error_message, kBufferSize); | 246 strerror_r(errno, os_error_message, kBufferSize); |
| 246 ASSERT(sizeof(child_errno) == sizeof(errno)); | 247 ASSERT(sizeof(child_errno) == sizeof(errno)); |
| 247 int bytes_written = | 248 int bytes_written = |
| 248 FDUtils::WriteToBlocking( | 249 FDUtils::WriteToBlocking( |
| 249 exec_control_fd, &child_errno, sizeof(child_errno)); | 250 exec_control_fd, &child_errno, sizeof(child_errno)); |
| 250 if (bytes_written == sizeof(child_errno)) { | 251 if (bytes_written == sizeof(child_errno)) { |
| 251 FDUtils::WriteToBlocking( | 252 FDUtils::WriteToBlocking( |
| 252 exec_control_fd, os_error_message, strlen(os_error_message) + 1); | 253 exec_control_fd, os_error_message, strlen(os_error_message) + 1); |
| 253 } | 254 } |
| 254 TEMP_FAILURE_RETRY(close(exec_control_fd)); | 255 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd)); |
| 255 exit(1); | 256 exit(1); |
| 256 } | 257 } |
| 257 | 258 |
| 258 | 259 |
| 259 int Process::Start(const char* path, | 260 int Process::Start(const char* path, |
| 260 char* arguments[], | 261 char* arguments[], |
| 261 intptr_t arguments_length, | 262 intptr_t arguments_length, |
| 262 const char* working_directory, | 263 const char* working_directory, |
| 263 char* environment[], | 264 char* environment[], |
| 264 intptr_t environment_length, | 265 intptr_t environment_length, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 279 if (result < 0) { | 280 if (result < 0) { |
| 280 SetChildOsErrorMessage(os_error_message); | 281 SetChildOsErrorMessage(os_error_message); |
| 281 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 282 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
| 282 return errno; | 283 return errno; |
| 283 } | 284 } |
| 284 FDUtils::SetCloseOnExec(read_in[0]); | 285 FDUtils::SetCloseOnExec(read_in[0]); |
| 285 | 286 |
| 286 result = TEMP_FAILURE_RETRY(pipe(read_err)); | 287 result = TEMP_FAILURE_RETRY(pipe(read_err)); |
| 287 if (result < 0) { | 288 if (result < 0) { |
| 288 SetChildOsErrorMessage(os_error_message); | 289 SetChildOsErrorMessage(os_error_message); |
| 289 TEMP_FAILURE_RETRY(close(read_in[0])); | 290 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 290 TEMP_FAILURE_RETRY(close(read_in[1])); | 291 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 291 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 292 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
| 292 return errno; | 293 return errno; |
| 293 } | 294 } |
| 294 FDUtils::SetCloseOnExec(read_err[0]); | 295 FDUtils::SetCloseOnExec(read_err[0]); |
| 295 | 296 |
| 296 result = TEMP_FAILURE_RETRY(pipe(write_out)); | 297 result = TEMP_FAILURE_RETRY(pipe(write_out)); |
| 297 if (result < 0) { | 298 if (result < 0) { |
| 298 SetChildOsErrorMessage(os_error_message); | 299 SetChildOsErrorMessage(os_error_message); |
| 299 TEMP_FAILURE_RETRY(close(read_in[0])); | 300 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 300 TEMP_FAILURE_RETRY(close(read_in[1])); | 301 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 301 TEMP_FAILURE_RETRY(close(read_err[0])); | 302 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 302 TEMP_FAILURE_RETRY(close(read_err[1])); | 303 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 303 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 304 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
| 304 return errno; | 305 return errno; |
| 305 } | 306 } |
| 306 FDUtils::SetCloseOnExec(write_out[1]); | 307 FDUtils::SetCloseOnExec(write_out[1]); |
| 307 | 308 |
| 308 result = TEMP_FAILURE_RETRY(pipe(exec_control)); | 309 result = TEMP_FAILURE_RETRY(pipe(exec_control)); |
| 309 if (result < 0) { | 310 if (result < 0) { |
| 310 SetChildOsErrorMessage(os_error_message); | 311 SetChildOsErrorMessage(os_error_message); |
| 311 TEMP_FAILURE_RETRY(close(read_in[0])); | 312 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 312 TEMP_FAILURE_RETRY(close(read_in[1])); | 313 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 313 TEMP_FAILURE_RETRY(close(read_err[0])); | 314 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 314 TEMP_FAILURE_RETRY(close(read_err[1])); | 315 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 315 TEMP_FAILURE_RETRY(close(write_out[0])); | 316 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 316 TEMP_FAILURE_RETRY(close(write_out[1])); | 317 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 317 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 318 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
| 318 return errno; | 319 return errno; |
| 319 } | 320 } |
| 320 FDUtils::SetCloseOnExec(exec_control[0]); | 321 FDUtils::SetCloseOnExec(exec_control[0]); |
| 321 FDUtils::SetCloseOnExec(exec_control[1]); | 322 FDUtils::SetCloseOnExec(exec_control[1]); |
| 322 | 323 |
| 323 if (result < 0) { | 324 if (result < 0) { |
| 324 SetChildOsErrorMessage(os_error_message); | 325 SetChildOsErrorMessage(os_error_message); |
| 325 TEMP_FAILURE_RETRY(close(read_in[0])); | 326 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 326 TEMP_FAILURE_RETRY(close(read_in[1])); | 327 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 327 TEMP_FAILURE_RETRY(close(read_err[0])); | 328 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 328 TEMP_FAILURE_RETRY(close(read_err[1])); | 329 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 329 TEMP_FAILURE_RETRY(close(write_out[0])); | 330 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 330 TEMP_FAILURE_RETRY(close(write_out[1])); | 331 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 331 TEMP_FAILURE_RETRY(close(exec_control[0])); | 332 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
| 332 TEMP_FAILURE_RETRY(close(exec_control[1])); | 333 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
| 333 Log::PrintErr("fcntl failed: %s\n", *os_error_message); | 334 Log::PrintErr("fcntl failed: %s\n", *os_error_message); |
| 334 return errno; | 335 return errno; |
| 335 } | 336 } |
| 336 | 337 |
| 337 char** program_arguments = new char*[arguments_length + 2]; | 338 char** program_arguments = new char*[arguments_length + 2]; |
| 338 program_arguments[0] = const_cast<char*>(path); | 339 program_arguments[0] = const_cast<char*>(path); |
| 339 for (int i = 0; i < arguments_length; i++) { | 340 for (int i = 0; i < arguments_length; i++) { |
| 340 program_arguments[i + 1] = arguments[i]; | 341 program_arguments[i + 1] = arguments[i]; |
| 341 } | 342 } |
| 342 program_arguments[arguments_length + 1] = NULL; | 343 program_arguments[arguments_length + 1] = NULL; |
| 343 | 344 |
| 344 char** program_environment = NULL; | 345 char** program_environment = NULL; |
| 345 if (environment != NULL) { | 346 if (environment != NULL) { |
| 346 program_environment = new char*[environment_length + 1]; | 347 program_environment = new char*[environment_length + 1]; |
| 347 for (int i = 0; i < environment_length; i++) { | 348 for (int i = 0; i < environment_length; i++) { |
| 348 program_environment[i] = environment[i]; | 349 program_environment[i] = environment[i]; |
| 349 } | 350 } |
| 350 program_environment[environment_length] = NULL; | 351 program_environment[environment_length] = NULL; |
| 351 } | 352 } |
| 352 | 353 |
| 353 pid = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fork()); | 354 pid = TEMP_FAILURE_RETRY(fork()); |
| 354 if (pid < 0) { | 355 if (pid < 0) { |
| 355 SetChildOsErrorMessage(os_error_message); | 356 SetChildOsErrorMessage(os_error_message); |
| 356 delete[] program_arguments; | 357 delete[] program_arguments; |
| 357 TEMP_FAILURE_RETRY(close(read_in[0])); | 358 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 358 TEMP_FAILURE_RETRY(close(read_in[1])); | 359 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 359 TEMP_FAILURE_RETRY(close(read_err[0])); | 360 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 360 TEMP_FAILURE_RETRY(close(read_err[1])); | 361 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 361 TEMP_FAILURE_RETRY(close(write_out[0])); | 362 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 362 TEMP_FAILURE_RETRY(close(write_out[1])); | 363 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 363 TEMP_FAILURE_RETRY(close(exec_control[0])); | 364 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
| 364 TEMP_FAILURE_RETRY(close(exec_control[1])); | 365 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
| 365 return errno; | 366 return errno; |
| 366 } else if (pid == 0) { | 367 } else if (pid == 0) { |
| 367 // Wait for parent process before setting up the child process. | 368 // Wait for parent process before setting up the child process. |
| 368 char msg; | 369 char msg; |
| 369 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); | 370 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); |
| 370 if (bytes_read != sizeof(msg)) { | 371 if (bytes_read != sizeof(msg)) { |
| 371 perror("Failed receiving notification message"); | 372 perror("Failed receiving notification message"); |
| 372 exit(1); | 373 exit(1); |
| 373 } | 374 } |
| 374 | 375 |
| 375 TEMP_FAILURE_RETRY(close(write_out[1])); | 376 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 376 TEMP_FAILURE_RETRY(close(read_in[0])); | 377 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 377 TEMP_FAILURE_RETRY(close(read_err[0])); | 378 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 378 TEMP_FAILURE_RETRY(close(exec_control[0])); | 379 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
| 379 | 380 |
| 380 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { | 381 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { |
| 381 ReportChildError(exec_control[1]); | 382 ReportChildError(exec_control[1]); |
| 382 } | 383 } |
| 383 TEMP_FAILURE_RETRY(close(write_out[0])); | 384 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 384 | 385 |
| 385 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { | 386 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { |
| 386 ReportChildError(exec_control[1]); | 387 ReportChildError(exec_control[1]); |
| 387 } | 388 } |
| 388 TEMP_FAILURE_RETRY(close(read_in[1])); | 389 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 389 | 390 |
| 390 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { | 391 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { |
| 391 ReportChildError(exec_control[1]); | 392 ReportChildError(exec_control[1]); |
| 392 } | 393 } |
| 393 TEMP_FAILURE_RETRY(close(read_err[1])); | 394 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 394 | 395 |
| 395 if (working_directory != NULL && | 396 if (working_directory != NULL && |
| 396 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { | 397 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { |
| 397 ReportChildError(exec_control[1]); | 398 ReportChildError(exec_control[1]); |
| 398 } | 399 } |
| 399 | 400 |
| 400 if (program_environment != NULL) { | 401 if (program_environment != NULL) { |
| 401 environ = program_environment; | 402 environ = program_environment; |
| 402 } | 403 } |
| 403 | 404 |
| 404 TEMP_FAILURE_RETRY( | 405 TEMP_FAILURE_RETRY( |
| 405 execvp(path, const_cast<char* const*>(program_arguments))); | 406 execvp(path, const_cast<char* const*>(program_arguments))); |
| 406 | 407 |
| 407 ReportChildError(exec_control[1]); | 408 ReportChildError(exec_control[1]); |
| 408 } | 409 } |
| 409 | 410 |
| 410 // Be sure to listen for exit-codes, now we have a child-process. | 411 // Be sure to listen for exit-codes, now we have a child-process. |
| 411 ExitCodeHandler::ProcessStarted(); | 412 ExitCodeHandler::ProcessStarted(); |
| 412 | 413 |
| 413 // The arguments and environment for the spawned process are not needed | 414 // The arguments and environment for the spawned process are not needed |
| 414 // any longer. | 415 // any longer. |
| 415 delete[] program_arguments; | 416 delete[] program_arguments; |
| 416 delete[] program_environment; | 417 delete[] program_environment; |
| 417 | 418 |
| 418 int event_fds[2]; | 419 int event_fds[2]; |
| 419 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 420 result = TEMP_FAILURE_RETRY(pipe(event_fds)); |
| 420 if (result < 0) { | 421 if (result < 0) { |
| 421 SetChildOsErrorMessage(os_error_message); | 422 SetChildOsErrorMessage(os_error_message); |
| 422 TEMP_FAILURE_RETRY(close(read_in[0])); | 423 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 423 TEMP_FAILURE_RETRY(close(read_in[1])); | 424 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 424 TEMP_FAILURE_RETRY(close(read_err[0])); | 425 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 425 TEMP_FAILURE_RETRY(close(read_err[1])); | 426 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 426 TEMP_FAILURE_RETRY(close(write_out[0])); | 427 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 427 TEMP_FAILURE_RETRY(close(write_out[1])); | 428 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 428 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 429 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
| 429 return errno; | 430 return errno; |
| 430 } | 431 } |
| 431 FDUtils::SetCloseOnExec(event_fds[0]); | 432 FDUtils::SetCloseOnExec(event_fds[0]); |
| 432 FDUtils::SetCloseOnExec(event_fds[1]); | 433 FDUtils::SetCloseOnExec(event_fds[1]); |
| 433 | 434 |
| 434 ProcessInfoList::AddProcess(pid, event_fds[1]); | 435 ProcessInfoList::AddProcess(pid, event_fds[1]); |
| 435 *exit_event = event_fds[0]; | 436 *exit_event = event_fds[0]; |
| 436 FDUtils::SetNonBlocking(event_fds[0]); | 437 FDUtils::SetNonBlocking(event_fds[0]); |
| 437 | 438 |
| 438 // Notify child process to start. | 439 // Notify child process to start. |
| 439 char msg = '1'; | 440 char msg = '1'; |
| 440 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); | 441 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); |
| 441 if (result != sizeof(msg)) { | 442 if (result != sizeof(msg)) { |
| 442 perror("Failed sending notification message"); | 443 perror("Failed sending notification message"); |
| 443 } | 444 } |
| 444 | 445 |
| 445 // Read exec result from child. If no data is returned the exec was | 446 // Read exec result from child. If no data is returned the exec was |
| 446 // successful and the exec call closed the pipe. Otherwise the errno | 447 // successful and the exec call closed the pipe. Otherwise the errno |
| 447 // is written to the pipe. | 448 // is written to the pipe. |
| 448 TEMP_FAILURE_RETRY(close(exec_control[1])); | 449 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
| 449 int child_errno; | 450 int child_errno; |
| 450 int bytes_read = -1; | 451 int bytes_read = -1; |
| 451 ASSERT(sizeof(child_errno) == sizeof(errno)); | 452 ASSERT(sizeof(child_errno) == sizeof(errno)); |
| 452 bytes_read = | 453 bytes_read = |
| 453 FDUtils::ReadFromBlocking( | 454 FDUtils::ReadFromBlocking( |
| 454 exec_control[0], &child_errno, sizeof(child_errno)); | 455 exec_control[0], &child_errno, sizeof(child_errno)); |
| 455 if (bytes_read == sizeof(child_errno)) { | 456 if (bytes_read == sizeof(child_errno)) { |
| 456 static const int kMaxMessageSize = 256; | 457 static const int kMaxMessageSize = 256; |
| 457 char* message = static_cast<char*>(malloc(kMaxMessageSize)); | 458 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
| 458 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], | 459 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], |
| 459 message, | 460 message, |
| 460 kMaxMessageSize); | 461 kMaxMessageSize); |
| 461 message[kMaxMessageSize - 1] = '\0'; | 462 message[kMaxMessageSize - 1] = '\0'; |
| 462 *os_error_message = message; | 463 *os_error_message = message; |
| 463 } | 464 } |
| 464 TEMP_FAILURE_RETRY(close(exec_control[0])); | 465 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
| 465 | 466 |
| 466 // Return error code if any failures. | 467 // Return error code if any failures. |
| 467 if (bytes_read != 0) { | 468 if (bytes_read != 0) { |
| 468 TEMP_FAILURE_RETRY(close(read_in[0])); | 469 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
| 469 TEMP_FAILURE_RETRY(close(read_in[1])); | 470 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 470 TEMP_FAILURE_RETRY(close(read_err[0])); | 471 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
| 471 TEMP_FAILURE_RETRY(close(read_err[1])); | 472 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 472 TEMP_FAILURE_RETRY(close(write_out[0])); | 473 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 473 TEMP_FAILURE_RETRY(close(write_out[1])); | 474 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
| 474 | 475 |
| 475 // Since exec() failed, we're not interested in the exit code. | 476 // Since exec() failed, we're not interested in the exit code. |
| 476 // We close the reading side of the exit code pipe here. | 477 // We close the reading side of the exit code pipe here. |
| 477 // GetProcessExitCodes will get a broken pipe error when it tries to write | 478 // GetProcessExitCodes will get a broken pipe error when it tries to write |
| 478 // to the writing side of the pipe and it will ignore the error. | 479 // to the writing side of the pipe and it will ignore the error. |
| 479 TEMP_FAILURE_RETRY(close(*exit_event)); | 480 VOID_TEMP_FAILURE_RETRY(close(*exit_event)); |
| 480 *exit_event = -1; | 481 *exit_event = -1; |
| 481 | 482 |
| 482 if (bytes_read == -1) { | 483 if (bytes_read == -1) { |
| 483 return errno; // Read failed. | 484 return errno; // Read failed. |
| 484 } else { | 485 } else { |
| 485 return child_errno; // Exec failed. | 486 return child_errno; // Exec failed. |
| 486 } | 487 } |
| 487 } | 488 } |
| 488 | 489 |
| 489 FDUtils::SetNonBlocking(read_in[0]); | 490 FDUtils::SetNonBlocking(read_in[0]); |
| 490 *in = read_in[0]; | 491 *in = read_in[0]; |
| 491 TEMP_FAILURE_RETRY(close(read_in[1])); | 492 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
| 492 FDUtils::SetNonBlocking(write_out[1]); | 493 FDUtils::SetNonBlocking(write_out[1]); |
| 493 *out = write_out[1]; | 494 *out = write_out[1]; |
| 494 TEMP_FAILURE_RETRY(close(write_out[0])); | 495 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
| 495 FDUtils::SetNonBlocking(read_err[0]); | 496 FDUtils::SetNonBlocking(read_err[0]); |
| 496 *err = read_err[0]; | 497 *err = read_err[0]; |
| 497 TEMP_FAILURE_RETRY(close(read_err[1])); | 498 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
| 498 | 499 |
| 499 *id = pid; | 500 *id = pid; |
| 500 return 0; | 501 return 0; |
| 501 } | 502 } |
| 502 | 503 |
| 503 | 504 |
| 504 class BufferList: public BufferListBase { | 505 class BufferList: public BufferListBase { |
| 505 public: | 506 public: |
| 506 bool Read(int fd, intptr_t available) { | 507 bool Read(int fd, intptr_t available) { |
| 507 // Read all available bytes. | 508 // Read all available bytes. |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 intptr_t Process::SetSignalHandler(intptr_t signal) { | 668 intptr_t Process::SetSignalHandler(intptr_t signal) { |
| 668 bool found = false; | 669 bool found = false; |
| 669 for (int i = 0; i < kSignalsCount; i++) { | 670 for (int i = 0; i < kSignalsCount; i++) { |
| 670 if (kSignals[i] == signal) { | 671 if (kSignals[i] == signal) { |
| 671 found = true; | 672 found = true; |
| 672 break; | 673 break; |
| 673 } | 674 } |
| 674 } | 675 } |
| 675 if (!found) return -1; | 676 if (!found) return -1; |
| 676 int fds[2]; | 677 int fds[2]; |
| 677 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) { | 678 if (NO_RETRY_EXPECTED(pipe(fds)) != 0) { |
| 678 return -1; | 679 return -1; |
| 679 } | 680 } |
| 680 if (!FDUtils::SetNonBlocking(fds[0])) { | 681 if (!FDUtils::SetNonBlocking(fds[0])) { |
| 681 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 682 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
| 682 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 683 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
| 683 return -1; | 684 return -1; |
| 684 } | 685 } |
| 685 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 686 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
| 686 MutexLocker lock(signal_mutex); | 687 MutexLocker lock(signal_mutex); |
| 687 SignalInfo* handler = signal_handlers; | 688 SignalInfo* handler = signal_handlers; |
| 688 bool listen = true; | 689 bool listen = true; |
| 689 while (handler != NULL) { | 690 while (handler != NULL) { |
| 690 if (handler->signal() == signal) { | 691 if (handler->signal() == signal) { |
| 691 listen = false; | 692 listen = false; |
| 692 break; | 693 break; |
| 693 } | 694 } |
| 694 handler = handler->next(); | 695 handler = handler->next(); |
| 695 } | 696 } |
| 696 if (listen) { | 697 if (listen) { |
| 697 struct sigaction act; | 698 struct sigaction act; |
| 698 bzero(&act, sizeof(act)); | 699 bzero(&act, sizeof(act)); |
| 699 act.sa_handler = SignalHandler; | 700 act.sa_handler = SignalHandler; |
| 700 sigemptyset(&act.sa_mask); | 701 sigemptyset(&act.sa_mask); |
| 701 for (int i = 0; i < kSignalsCount; i++) { | 702 for (int i = 0; i < kSignalsCount; i++) { |
| 702 sigaddset(&act.sa_mask, kSignals[i]); | 703 sigaddset(&act.sa_mask, kSignals[i]); |
| 703 } | 704 } |
| 704 int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 705 int status = NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 705 sigaction(signal, &act, NULL)); | |
| 706 if (status < 0) { | 706 if (status < 0) { |
| 707 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 707 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
| 708 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 708 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
| 709 return -1; | 709 return -1; |
| 710 } | 710 } |
| 711 } | 711 } |
| 712 if (signal_handlers == NULL) { | 712 if (signal_handlers == NULL) { |
| 713 signal_handlers = new SignalInfo(fds[1], signal); | 713 signal_handlers = new SignalInfo(fds[1], signal); |
| 714 } else { | 714 } else { |
| 715 new SignalInfo(fds[1], signal, signal_handlers); | 715 new SignalInfo(fds[1], signal, signal_handlers); |
| 716 } | 716 } |
| 717 return fds[0]; | 717 return fds[0]; |
| 718 } | 718 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 735 } | 735 } |
| 736 } | 736 } |
| 737 SignalInfo* next = handler->next(); | 737 SignalInfo* next = handler->next(); |
| 738 if (remove) delete handler; | 738 if (remove) delete handler; |
| 739 handler = next; | 739 handler = next; |
| 740 } | 740 } |
| 741 if (unlisten) { | 741 if (unlisten) { |
| 742 struct sigaction act; | 742 struct sigaction act; |
| 743 bzero(&act, sizeof(act)); | 743 bzero(&act, sizeof(act)); |
| 744 act.sa_handler = SIG_DFL; | 744 act.sa_handler = SIG_DFL; |
| 745 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL)); | 745 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 746 } | 746 } |
| 747 } | 747 } |
| 748 | 748 |
| 749 } // namespace bin | 749 } // namespace bin |
| 750 } // namespace dart | 750 } // namespace dart |
| 751 | 751 |
| 752 #endif // defined(TARGET_OS_ANDROID) | 752 #endif // defined(TARGET_OS_ANDROID) |
| OLD | NEW |