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

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

Powered by Google App Engine
This is Rietveld 408576698