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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 }; | 251 }; |
252 | 252 |
253 | 253 |
254 dart::Mutex ExitCodeHandler::mutex_; | 254 dart::Mutex ExitCodeHandler::mutex_; |
255 bool ExitCodeHandler::initialized_ = false; | 255 bool ExitCodeHandler::initialized_ = false; |
256 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 }; | 256 int ExitCodeHandler::sig_chld_fds_[2] = { 0, 0 }; |
257 bool ExitCodeHandler::thread_terminated_ = false; | 257 bool ExitCodeHandler::thread_terminated_ = false; |
258 dart::Monitor ExitCodeHandler::thread_terminate_monitor_; | 258 dart::Monitor ExitCodeHandler::thread_terminate_monitor_; |
259 | 259 |
260 | 260 |
261 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { | 261 static void SetChildOsErrorMessage(char** os_error_message) { |
262 strncpy(dest, src, n); | 262 *os_error_message = strdup(strerror(errno)); |
263 dest[n - 1] = '\0'; | |
264 return dest; | |
265 } | 263 } |
266 | 264 |
267 | 265 |
268 static void SetChildOsErrorMessage(char* os_error_message, | |
269 int os_error_message_len) { | |
270 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); | |
271 } | |
272 | |
273 | |
274 static void SigChldHandler(int process_signal, siginfo_t* siginfo, void* tmp) { | 266 static void SigChldHandler(int process_signal, siginfo_t* siginfo, void* tmp) { |
275 // Save errno so it can be restored at the end. | 267 // Save errno so it can be restored at the end. |
276 int entry_errno = errno; | 268 int entry_errno = errno; |
277 // Signal the exit code handler where the actual processing takes | 269 // Signal the exit code handler where the actual processing takes |
278 // place. | 270 // place. |
279 ssize_t result = | 271 ssize_t result = |
280 TEMP_FAILURE_RETRY(write(ExitCodeHandler::WakeUpFd(), "", 1)); | 272 TEMP_FAILURE_RETRY(write(ExitCodeHandler::WakeUpFd(), "", 1)); |
281 if (result < 1) { | 273 if (result < 1) { |
282 perror("Failed to write to wake-up fd in SIGCHLD handler"); | 274 perror("Failed to write to wake-up fd in SIGCHLD handler"); |
283 } | 275 } |
(...skipping 24 matching lines...) Expand all Loading... |
308 char* arguments[], | 300 char* arguments[], |
309 intptr_t arguments_length, | 301 intptr_t arguments_length, |
310 const char* working_directory, | 302 const char* working_directory, |
311 char* environment[], | 303 char* environment[], |
312 intptr_t environment_length, | 304 intptr_t environment_length, |
313 intptr_t* in, | 305 intptr_t* in, |
314 intptr_t* out, | 306 intptr_t* out, |
315 intptr_t* err, | 307 intptr_t* err, |
316 intptr_t* id, | 308 intptr_t* id, |
317 intptr_t* exit_event, | 309 intptr_t* exit_event, |
318 char* os_error_message, | 310 char** os_error_message) { |
319 int os_error_message_len) { | |
320 pid_t pid; | 311 pid_t pid; |
321 int read_in[2]; // Pipe for stdout to child process. | 312 int read_in[2]; // Pipe for stdout to child process. |
322 int read_err[2]; // Pipe for stderr to child process. | 313 int read_err[2]; // Pipe for stderr to child process. |
323 int write_out[2]; // Pipe for stdin to child process. | 314 int write_out[2]; // Pipe for stdin to child process. |
324 int exec_control[2]; // Pipe to get the result from exec. | 315 int exec_control[2]; // Pipe to get the result from exec. |
325 int result; | 316 int result; |
326 | 317 |
327 bool initialized = ExitCodeHandler::EnsureInitialized(); | 318 bool initialized = ExitCodeHandler::EnsureInitialized(); |
328 if (!initialized) { | 319 if (!initialized) { |
329 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 320 SetChildOsErrorMessage(os_error_message); |
330 Log::PrintErr("Error initializing exit code handler: %s\n", | 321 Log::PrintErr("Error initializing exit code handler: %s\n", |
331 os_error_message); | 322 *os_error_message); |
332 return errno; | 323 return errno; |
333 } | 324 } |
334 | 325 |
335 result = TEMP_FAILURE_RETRY(pipe(read_in)); | 326 result = TEMP_FAILURE_RETRY(pipe(read_in)); |
336 if (result < 0) { | 327 if (result < 0) { |
337 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 328 SetChildOsErrorMessage(os_error_message); |
338 Log::PrintErr("Error pipe creation failed: %s\n", os_error_message); | 329 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
339 return errno; | 330 return errno; |
340 } | 331 } |
341 | 332 |
342 result = TEMP_FAILURE_RETRY(pipe(read_err)); | 333 result = TEMP_FAILURE_RETRY(pipe(read_err)); |
343 if (result < 0) { | 334 if (result < 0) { |
344 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 335 SetChildOsErrorMessage(os_error_message); |
345 TEMP_FAILURE_RETRY(close(read_in[0])); | 336 TEMP_FAILURE_RETRY(close(read_in[0])); |
346 TEMP_FAILURE_RETRY(close(read_in[1])); | 337 TEMP_FAILURE_RETRY(close(read_in[1])); |
347 Log::PrintErr("Error pipe creation failed: %s\n", os_error_message); | 338 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
348 return errno; | 339 return errno; |
349 } | 340 } |
350 | 341 |
351 result = TEMP_FAILURE_RETRY(pipe(write_out)); | 342 result = TEMP_FAILURE_RETRY(pipe(write_out)); |
352 if (result < 0) { | 343 if (result < 0) { |
353 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 344 SetChildOsErrorMessage(os_error_message); |
354 TEMP_FAILURE_RETRY(close(read_in[0])); | 345 TEMP_FAILURE_RETRY(close(read_in[0])); |
355 TEMP_FAILURE_RETRY(close(read_in[1])); | 346 TEMP_FAILURE_RETRY(close(read_in[1])); |
356 TEMP_FAILURE_RETRY(close(read_err[0])); | 347 TEMP_FAILURE_RETRY(close(read_err[0])); |
357 TEMP_FAILURE_RETRY(close(read_err[1])); | 348 TEMP_FAILURE_RETRY(close(read_err[1])); |
358 Log::PrintErr("Error pipe creation failed: %s\n", os_error_message); | 349 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
359 return errno; | 350 return errno; |
360 } | 351 } |
361 | 352 |
362 result = TEMP_FAILURE_RETRY(pipe(exec_control)); | 353 result = TEMP_FAILURE_RETRY(pipe(exec_control)); |
363 if (result < 0) { | 354 if (result < 0) { |
364 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 355 SetChildOsErrorMessage(os_error_message); |
365 TEMP_FAILURE_RETRY(close(read_in[0])); | 356 TEMP_FAILURE_RETRY(close(read_in[0])); |
366 TEMP_FAILURE_RETRY(close(read_in[1])); | 357 TEMP_FAILURE_RETRY(close(read_in[1])); |
367 TEMP_FAILURE_RETRY(close(read_err[0])); | 358 TEMP_FAILURE_RETRY(close(read_err[0])); |
368 TEMP_FAILURE_RETRY(close(read_err[1])); | 359 TEMP_FAILURE_RETRY(close(read_err[1])); |
369 TEMP_FAILURE_RETRY(close(write_out[0])); | 360 TEMP_FAILURE_RETRY(close(write_out[0])); |
370 TEMP_FAILURE_RETRY(close(write_out[1])); | 361 TEMP_FAILURE_RETRY(close(write_out[1])); |
371 Log::PrintErr("Error pipe creation failed: %s\n", os_error_message); | 362 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
372 return errno; | 363 return errno; |
373 } | 364 } |
374 | 365 |
375 // Set close on exec on the write file descriptor of the exec control pipe. | 366 // Set close on exec on the write file descriptor of the exec control pipe. |
376 result = TEMP_FAILURE_RETRY( | 367 result = TEMP_FAILURE_RETRY( |
377 fcntl(exec_control[1], | 368 fcntl(exec_control[1], |
378 F_SETFD, | 369 F_SETFD, |
379 TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC)); | 370 TEMP_FAILURE_RETRY(fcntl(exec_control[1], F_GETFD)) | FD_CLOEXEC)); |
380 if (result < 0) { | 371 if (result < 0) { |
381 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 372 SetChildOsErrorMessage(os_error_message); |
382 TEMP_FAILURE_RETRY(close(read_in[0])); | 373 TEMP_FAILURE_RETRY(close(read_in[0])); |
383 TEMP_FAILURE_RETRY(close(read_in[1])); | 374 TEMP_FAILURE_RETRY(close(read_in[1])); |
384 TEMP_FAILURE_RETRY(close(read_err[0])); | 375 TEMP_FAILURE_RETRY(close(read_err[0])); |
385 TEMP_FAILURE_RETRY(close(read_err[1])); | 376 TEMP_FAILURE_RETRY(close(read_err[1])); |
386 TEMP_FAILURE_RETRY(close(write_out[0])); | 377 TEMP_FAILURE_RETRY(close(write_out[0])); |
387 TEMP_FAILURE_RETRY(close(write_out[1])); | 378 TEMP_FAILURE_RETRY(close(write_out[1])); |
388 TEMP_FAILURE_RETRY(close(exec_control[0])); | 379 TEMP_FAILURE_RETRY(close(exec_control[0])); |
389 TEMP_FAILURE_RETRY(close(exec_control[1])); | 380 TEMP_FAILURE_RETRY(close(exec_control[1])); |
390 Log::PrintErr("fcntl failed: %s\n", os_error_message); | 381 Log::PrintErr("fcntl failed: %s\n", *os_error_message); |
391 return errno; | 382 return errno; |
392 } | 383 } |
393 | 384 |
394 char** program_arguments = new char*[arguments_length + 2]; | 385 char** program_arguments = new char*[arguments_length + 2]; |
395 program_arguments[0] = const_cast<char*>(path); | 386 program_arguments[0] = const_cast<char*>(path); |
396 for (int i = 0; i < arguments_length; i++) { | 387 for (int i = 0; i < arguments_length; i++) { |
397 program_arguments[i + 1] = arguments[i]; | 388 program_arguments[i + 1] = arguments[i]; |
398 } | 389 } |
399 program_arguments[arguments_length + 1] = NULL; | 390 program_arguments[arguments_length + 1] = NULL; |
400 | 391 |
401 char** program_environment = NULL; | 392 char** program_environment = NULL; |
402 if (environment != NULL) { | 393 if (environment != NULL) { |
403 program_environment = new char*[environment_length + 1]; | 394 program_environment = new char*[environment_length + 1]; |
404 for (int i = 0; i < environment_length; i++) { | 395 for (int i = 0; i < environment_length; i++) { |
405 program_environment[i] = environment[i]; | 396 program_environment[i] = environment[i]; |
406 } | 397 } |
407 program_environment[environment_length] = NULL; | 398 program_environment[environment_length] = NULL; |
408 } | 399 } |
409 | 400 |
410 struct sigaction act; | 401 struct sigaction act; |
411 bzero(&act, sizeof(act)); | 402 bzero(&act, sizeof(act)); |
412 act.sa_sigaction = SigChldHandler; | 403 act.sa_sigaction = SigChldHandler; |
413 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; | 404 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; |
414 if (sigaction(SIGCHLD, &act, 0) != 0) { | 405 if (sigaction(SIGCHLD, &act, 0) != 0) { |
415 perror("Process start: setting signal handler failed"); | 406 perror("Process start: setting signal handler failed"); |
416 } | 407 } |
417 pid = TEMP_FAILURE_RETRY(fork()); | 408 pid = TEMP_FAILURE_RETRY(fork()); |
418 if (pid < 0) { | 409 if (pid < 0) { |
419 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 410 SetChildOsErrorMessage(os_error_message); |
420 delete[] program_arguments; | 411 delete[] program_arguments; |
421 TEMP_FAILURE_RETRY(close(read_in[0])); | 412 TEMP_FAILURE_RETRY(close(read_in[0])); |
422 TEMP_FAILURE_RETRY(close(read_in[1])); | 413 TEMP_FAILURE_RETRY(close(read_in[1])); |
423 TEMP_FAILURE_RETRY(close(read_err[0])); | 414 TEMP_FAILURE_RETRY(close(read_err[0])); |
424 TEMP_FAILURE_RETRY(close(read_err[1])); | 415 TEMP_FAILURE_RETRY(close(read_err[1])); |
425 TEMP_FAILURE_RETRY(close(write_out[0])); | 416 TEMP_FAILURE_RETRY(close(write_out[0])); |
426 TEMP_FAILURE_RETRY(close(write_out[1])); | 417 TEMP_FAILURE_RETRY(close(write_out[1])); |
427 TEMP_FAILURE_RETRY(close(exec_control[0])); | 418 TEMP_FAILURE_RETRY(close(exec_control[0])); |
428 TEMP_FAILURE_RETRY(close(exec_control[1])); | 419 TEMP_FAILURE_RETRY(close(exec_control[1])); |
429 return errno; | 420 return errno; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 } | 463 } |
473 | 464 |
474 // The arguments and environment for the spawned process are not needed | 465 // The arguments and environment for the spawned process are not needed |
475 // any longer. | 466 // any longer. |
476 delete[] program_arguments; | 467 delete[] program_arguments; |
477 delete[] program_environment; | 468 delete[] program_environment; |
478 | 469 |
479 int event_fds[2]; | 470 int event_fds[2]; |
480 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 471 result = TEMP_FAILURE_RETRY(pipe(event_fds)); |
481 if (result < 0) { | 472 if (result < 0) { |
482 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 473 SetChildOsErrorMessage(os_error_message); |
483 TEMP_FAILURE_RETRY(close(read_in[0])); | 474 TEMP_FAILURE_RETRY(close(read_in[0])); |
484 TEMP_FAILURE_RETRY(close(read_in[1])); | 475 TEMP_FAILURE_RETRY(close(read_in[1])); |
485 TEMP_FAILURE_RETRY(close(read_err[0])); | 476 TEMP_FAILURE_RETRY(close(read_err[0])); |
486 TEMP_FAILURE_RETRY(close(read_err[1])); | 477 TEMP_FAILURE_RETRY(close(read_err[1])); |
487 TEMP_FAILURE_RETRY(close(write_out[0])); | 478 TEMP_FAILURE_RETRY(close(write_out[0])); |
488 TEMP_FAILURE_RETRY(close(write_out[1])); | 479 TEMP_FAILURE_RETRY(close(write_out[1])); |
489 Log::PrintErr("Error pipe creation failed: %s\n", os_error_message); | 480 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
490 return errno; | 481 return errno; |
491 } | 482 } |
492 | 483 |
493 ProcessInfoList::AddProcess(pid, event_fds[1]); | 484 ProcessInfoList::AddProcess(pid, event_fds[1]); |
494 *exit_event = event_fds[0]; | 485 *exit_event = event_fds[0]; |
495 FDUtils::SetNonBlocking(event_fds[0]); | 486 FDUtils::SetNonBlocking(event_fds[0]); |
496 | 487 |
497 // Notify child process to start. | 488 // Notify child process to start. |
498 char msg = '1'; | 489 char msg = '1'; |
499 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); | 490 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); |
500 if (result != sizeof(msg)) { | 491 if (result != sizeof(msg)) { |
501 perror("Failed sending notification message"); | 492 perror("Failed sending notification message"); |
502 } | 493 } |
503 | 494 |
504 // Read exec result from child. If no data is returned the exec was | 495 // Read exec result from child. If no data is returned the exec was |
505 // successful and the exec call closed the pipe. Otherwise the errno | 496 // successful and the exec call closed the pipe. Otherwise the errno |
506 // is written to the pipe. | 497 // is written to the pipe. |
507 TEMP_FAILURE_RETRY(close(exec_control[1])); | 498 TEMP_FAILURE_RETRY(close(exec_control[1])); |
508 int child_errno; | 499 int child_errno; |
509 int bytes_read = -1; | 500 int bytes_read = -1; |
510 ASSERT(sizeof(child_errno) == sizeof(errno)); | 501 ASSERT(sizeof(child_errno) == sizeof(errno)); |
511 bytes_read = | 502 bytes_read = |
512 FDUtils::ReadFromBlocking( | 503 FDUtils::ReadFromBlocking( |
513 exec_control[0], &child_errno, sizeof(child_errno)); | 504 exec_control[0], &child_errno, sizeof(child_errno)); |
514 if (bytes_read == sizeof(child_errno)) { | 505 if (bytes_read == sizeof(child_errno)) { |
515 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], | 506 static const int kMaxMessageSize = 256; |
516 os_error_message, | 507 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
517 os_error_message_len); | 508 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], |
518 os_error_message[os_error_message_len - 1] = '\0'; | 509 message, |
| 510 kMaxMessageSize); |
| 511 message[kMaxMessageSize - 1] = '\0'; |
| 512 *os_error_message = message; |
519 } | 513 } |
520 TEMP_FAILURE_RETRY(close(exec_control[0])); | 514 TEMP_FAILURE_RETRY(close(exec_control[0])); |
521 | 515 |
522 // Return error code if any failures. | 516 // Return error code if any failures. |
523 if (bytes_read != 0) { | 517 if (bytes_read != 0) { |
524 TEMP_FAILURE_RETRY(close(read_in[0])); | 518 TEMP_FAILURE_RETRY(close(read_in[0])); |
525 TEMP_FAILURE_RETRY(close(read_in[1])); | 519 TEMP_FAILURE_RETRY(close(read_in[1])); |
526 TEMP_FAILURE_RETRY(close(read_err[0])); | 520 TEMP_FAILURE_RETRY(close(read_err[0])); |
527 TEMP_FAILURE_RETRY(close(read_err[1])); | 521 TEMP_FAILURE_RETRY(close(read_err[1])); |
528 TEMP_FAILURE_RETRY(close(write_out[0])); | 522 TEMP_FAILURE_RETRY(close(write_out[0])); |
(...skipping 26 matching lines...) Expand all Loading... |
555 | 549 |
556 | 550 |
557 void Process::TerminateExitCodeHandler() { | 551 void Process::TerminateExitCodeHandler() { |
558 ExitCodeHandler::TerminateExitCodeThread(); | 552 ExitCodeHandler::TerminateExitCodeThread(); |
559 } | 553 } |
560 | 554 |
561 | 555 |
562 intptr_t Process::CurrentProcessId() { | 556 intptr_t Process::CurrentProcessId() { |
563 return static_cast<intptr_t>(getpid()); | 557 return static_cast<intptr_t>(getpid()); |
564 } | 558 } |
OLD | NEW |