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