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

Unified Diff: base/process/launch_win.cc

Issue 1291553003: Print stack traces in child processes when browser tests failed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: patch 1295823002 which fixes the console coming up on Win8+ and adds regression tests Created 5 years, 4 months 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 side-by-side diff with in-line comments
Download patch
Index: base/process/launch_win.cc
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index fa59f1ae90744469e397d3bd778cb8b1e98150c4..324eee7365aebfefaff619d44b9e64cecbb6aab4 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -46,9 +46,91 @@ namespace {
// process goes away.
const DWORD kProcessKilledExitCode = 1;
+bool GetAppOutputInternal(const StringPiece16& cl,
+ bool include_stderr,
+ std::string* output) {
+ HANDLE out_read = NULL;
+ HANDLE out_write = NULL;
+
+ SECURITY_ATTRIBUTES sa_attr;
+ // Set the bInheritHandle flag so pipe handles are inherited.
+ sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa_attr.bInheritHandle = TRUE;
+ sa_attr.lpSecurityDescriptor = NULL;
+
+ // Create the pipe for the child process's STDOUT.
+ if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
+ NOTREACHED() << "Failed to create pipe";
+ return false;
+ }
+
+ // Ensure we don't leak the handles.
+ win::ScopedHandle scoped_out_read(out_read);
+ win::ScopedHandle scoped_out_write(out_write);
+
+ // Ensure the read handles to the pipes are not inherited.
+ if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
+ NOTREACHED() << "Failed to disabled pipe inheritance";
+ return false;
+ }
+
+ FilePath::StringType writable_command_line_string;
+ writable_command_line_string.assign(cl.data(), cl.size());
+
+ STARTUPINFO start_info = {};
+
+ start_info.cb = sizeof(STARTUPINFO);
+ start_info.hStdOutput = out_write;
+ // Keep the normal stdin.
+ start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ if (include_stderr) {
+ start_info.hStdError = out_write;
+ } else {
+ start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ }
+ start_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ // Create the child process.
+ PROCESS_INFORMATION temp_process_info = {};
+ if (!CreateProcess(NULL,
+ &writable_command_line_string[0],
+ NULL, NULL,
+ TRUE, // Handles are inherited.
+ 0, NULL, NULL, &start_info, &temp_process_info)) {
+ NOTREACHED() << "Failed to start process";
+ return false;
+ }
+ base::win::ScopedProcessInformation proc_info(temp_process_info);
+
+ // Close our writing end of pipe now. Otherwise later read would not be able
+ // to detect end of child's output.
+ scoped_out_write.Close();
+
+ // Read output from the child process's pipe for STDOUT
+ const int kBufferSize = 1024;
+ char buffer[kBufferSize];
+
+ for (;;) {
+ DWORD bytes_read = 0;
+ BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL);
+ if (!success || bytes_read == 0)
+ break;
+ output->append(buffer, bytes_read);
+ }
+
+ // Let's wait for the process to finish.
+ WaitForSingleObject(proc_info.process_handle(), INFINITE);
+
+ int exit_code;
+ base::TerminationStatus status = GetTerminationStatus(
+ proc_info.process_handle(), &exit_code);
+ return status != base::TERMINATION_STATUS_PROCESS_CRASHED &&
+ status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION;
+}
+
} // namespace
-void RouteStdioToConsole() {
+void RouteStdioToConsole(bool create_console_if_not_found) {
// Don't change anything if stdout or stderr already point to a
// valid stream.
//
@@ -64,8 +146,22 @@ void RouteStdioToConsole() {
// stdout/stderr on startup (before the handle IDs can be reused).
// _fileno(stdout) will return -2 (_NO_CONSOLE_FILENO) if stdout was
// invalid.
- if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0)
- return;
+ if (_fileno(stdout) >= 0 || _fileno(stderr) >= 0) {
+ // _fileno was broken for SUBSYSTEM:WINDOWS from VS2010 to VS2012/2013.
+ // http://crbug.com/358267. Confirm that the underlying HANDLE is valid
+ // before aborting.
+
+ // This causes NaCl tests to hang on XP for reasons unclear, perhaps due
+ // to not being able to inherit handles. Since it's only for debugging,
+ // and redirecting still works, punt for now.
+ if (base::win::GetVersion() < base::win::VERSION_VISTA)
+ return;
+
+ intptr_t stdout_handle = _get_osfhandle(_fileno(stdout));
+ intptr_t stderr_handle = _get_osfhandle(_fileno(stderr));
+ if (stdout_handle >= 0 || stderr_handle >= 0)
+ return;
+ }
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
unsigned int result = GetLastError();
@@ -76,10 +172,12 @@ void RouteStdioToConsole() {
// parent process is invalid (eg: crashed).
if (result == ERROR_GEN_FAILURE)
return;
- // Make a new console if attaching to parent fails with any other error.
- // It should be ERROR_INVALID_HANDLE at this point, which means the browser
- // was likely not started from a console.
- AllocConsole();
+ if (create_console_if_not_found) {
+ // Make a new console if attaching to parent fails with any other error.
+ // It should be ERROR_INVALID_HANDLE at this point, which means the
+ // browser was likely not started from a console.
+ AllocConsole();
+ }
}
// Arbitrary byte count to use when buffering output lines. More
@@ -274,76 +372,12 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
return GetAppOutput(cl.GetCommandLineString(), output);
}
-bool GetAppOutput(const StringPiece16& cl, std::string* output) {
- HANDLE out_read = NULL;
- HANDLE out_write = NULL;
-
- SECURITY_ATTRIBUTES sa_attr;
- // Set the bInheritHandle flag so pipe handles are inherited.
- sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa_attr.bInheritHandle = TRUE;
- sa_attr.lpSecurityDescriptor = NULL;
-
- // Create the pipe for the child process's STDOUT.
- if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
- NOTREACHED() << "Failed to create pipe";
- return false;
- }
-
- // Ensure we don't leak the handles.
- win::ScopedHandle scoped_out_read(out_read);
- win::ScopedHandle scoped_out_write(out_write);
-
- // Ensure the read handle to the pipe for STDOUT is not inherited.
- if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
- NOTREACHED() << "Failed to disabled pipe inheritance";
- return false;
- }
-
- FilePath::StringType writable_command_line_string;
- writable_command_line_string.assign(cl.data(), cl.size());
-
- STARTUPINFO start_info = {};
-
- start_info.cb = sizeof(STARTUPINFO);
- start_info.hStdOutput = out_write;
- // Keep the normal stdin and stderr.
- start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- start_info.dwFlags |= STARTF_USESTDHANDLES;
-
- // Create the child process.
- PROCESS_INFORMATION temp_process_info = {};
- if (!CreateProcess(NULL,
- &writable_command_line_string[0],
- NULL, NULL,
- TRUE, // Handles are inherited.
- 0, NULL, NULL, &start_info, &temp_process_info)) {
- NOTREACHED() << "Failed to start process";
- return false;
- }
- base::win::ScopedProcessInformation proc_info(temp_process_info);
-
- // Close our writing end of pipe now. Otherwise later read would not be able
- // to detect end of child's output.
- scoped_out_write.Close();
-
- // Read output from the child process's pipe for STDOUT
- const int kBufferSize = 1024;
- char buffer[kBufferSize];
-
- for (;;) {
- DWORD bytes_read = 0;
- BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL);
- if (!success || bytes_read == 0)
- break;
- output->append(buffer, bytes_read);
- }
-
- // Let's wait for the process to finish.
- WaitForSingleObject(proc_info.process_handle(), INFINITE);
+bool GetAppOutputAndError(const CommandLine& cl, std::string* output) {
+ return GetAppOutputInternal(cl.GetCommandLineString(), true, output);
+}
- return true;
+bool GetAppOutput(const StringPiece16& cl, std::string* output) {
+ return GetAppOutputInternal(cl, false, output);
}
void RaiseProcessToHighPriority() {

Powered by Google App Engine
This is Rietveld 408576698