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

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

Issue 11558012: Use FormatMessageW for Windows error messages to handle internationalized messages correctly. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years 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
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698