OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process_util.h" | 5 #include "base/process_util.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <io.h> | 8 #include <io.h> |
9 #include <windows.h> | 9 #include <windows.h> |
10 #include <userenv.h> | 10 #include <userenv.h> |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 // Prints the exception call stack. | 63 // Prints the exception call stack. |
64 // This is the unit tests exception filter. | 64 // This is the unit tests exception filter. |
65 long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { | 65 long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { |
66 debug::StackTrace(info).PrintBacktrace(); | 66 debug::StackTrace(info).PrintBacktrace(); |
67 if (g_previous_filter) | 67 if (g_previous_filter) |
68 return g_previous_filter(info); | 68 return g_previous_filter(info); |
69 return EXCEPTION_CONTINUE_SEARCH; | 69 return EXCEPTION_CONTINUE_SEARCH; |
70 } | 70 } |
71 | 71 |
72 // Connects back to a console if available. | |
73 void AttachToConsole() { | |
74 if (!AttachConsole(ATTACH_PARENT_PROCESS)) { | |
75 unsigned int result = GetLastError(); | |
76 // Was probably already attached. | |
77 if (result == ERROR_ACCESS_DENIED) | |
78 return; | |
79 | |
80 if (result == ERROR_INVALID_HANDLE || result == ERROR_INVALID_HANDLE) { | |
81 // TODO(maruel): Walk up the process chain if deemed necessary. | |
82 } | |
83 // Continue even if the function call fails. | |
84 AllocConsole(); | |
85 } | |
86 // http://support.microsoft.com/kb/105305 | |
87 int raw_out = _open_osfhandle( | |
88 reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE)), _O_TEXT); | |
89 *stdout = *_fdopen(raw_out, "w"); | |
90 setvbuf(stdout, NULL, _IONBF, 0); | |
91 | |
92 int raw_err = _open_osfhandle( | |
93 reinterpret_cast<intptr_t>(GetStdHandle(STD_ERROR_HANDLE)), _O_TEXT); | |
94 *stderr = *_fdopen(raw_err, "w"); | |
95 setvbuf(stderr, NULL, _IONBF, 0); | |
96 | |
97 int raw_in = _open_osfhandle( | |
98 reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE)), _O_TEXT); | |
99 *stdin = *_fdopen(raw_in, "r"); | |
100 setvbuf(stdin, NULL, _IONBF, 0); | |
101 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. | |
102 std::ios::sync_with_stdio(); | |
103 } | |
104 | |
105 void OnNoMemory() { | 72 void OnNoMemory() { |
106 // Kill the process. This is important for security, since WebKit doesn't | 73 // Kill the process. This is important for security, since WebKit doesn't |
107 // NULL-check many memory allocations. If a malloc fails, returns NULL, and | 74 // NULL-check many memory allocations. If a malloc fails, returns NULL, and |
108 // the buffer is then used, it provides a handy mapping of memory starting at | 75 // the buffer is then used, it provides a handy mapping of memory starting at |
109 // address 0 for an attacker to utilize. | 76 // address 0 for an attacker to utilize. |
110 __debugbreak(); | 77 __debugbreak(); |
111 _exit(1); | 78 _exit(1); |
112 } | 79 } |
113 | 80 |
114 class TimerExpiredTask : public win::ObjectWatcher::Delegate { | 81 class TimerExpiredTask : public win::ObjectWatcher::Delegate { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 // TerminateProcess should do for us. Don't check for the result code since | 127 // TerminateProcess should do for us. Don't check for the result code since |
161 // it fails quite often. This should be investigated eventually. | 128 // it fails quite often. This should be investigated eventually. |
162 base::KillProcess(process_, kProcessKilledExitCode, false); | 129 base::KillProcess(process_, kProcessKilledExitCode, false); |
163 | 130 |
164 // Now, just cleanup as if the process exited normally. | 131 // Now, just cleanup as if the process exited normally. |
165 OnObjectSignaled(process_); | 132 OnObjectSignaled(process_); |
166 } | 133 } |
167 | 134 |
168 } // namespace | 135 } // namespace |
169 | 136 |
| 137 void RouteStdioToConsole() { |
| 138 if (!AttachConsole(ATTACH_PARENT_PROCESS)) { |
| 139 unsigned int result = GetLastError(); |
| 140 // Was probably already attached. |
| 141 if (result == ERROR_ACCESS_DENIED) |
| 142 return; |
| 143 // Don't bother creating a new console for each child process if the |
| 144 // parent process is invalid (eg: crashed). |
| 145 if (result == ERROR_GEN_FAILURE) |
| 146 return; |
| 147 // Make a new console if attaching to parent fails with any other error. |
| 148 // It should be ERROR_INVALID_HANDLE at this point, which means the browser |
| 149 // was likely not started from a console. |
| 150 AllocConsole(); |
| 151 } |
| 152 |
| 153 if (freopen("CONOUT$", "w", stdout)) |
| 154 setvbuf(stdout, NULL, _IONBF, 0); |
| 155 if (freopen("CONERR$", "w", stderr)) |
| 156 setvbuf(stderr, NULL, _IONBF, 0); |
| 157 |
| 158 // Fix all cout, wcout, cin, wcin, cerr, wcerr, clog and wclog. |
| 159 std::ios::sync_with_stdio(); |
| 160 } |
| 161 |
170 ProcessId GetCurrentProcId() { | 162 ProcessId GetCurrentProcId() { |
171 return ::GetCurrentProcessId(); | 163 return ::GetCurrentProcessId(); |
172 } | 164 } |
173 | 165 |
174 ProcessHandle GetCurrentProcessHandle() { | 166 ProcessHandle GetCurrentProcessHandle() { |
175 return ::GetCurrentProcess(); | 167 return ::GetCurrentProcess(); |
176 } | 168 } |
177 | 169 |
178 HMODULE GetModuleFromAddress(void* address) { | 170 HMODULE GetModuleFromAddress(void* address) { |
179 HMODULE instance = NULL; | 171 HMODULE instance = NULL; |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 } | 939 } |
948 | 940 |
949 void EnableTerminationOnOutOfMemory() { | 941 void EnableTerminationOnOutOfMemory() { |
950 std::set_new_handler(&OnNoMemory); | 942 std::set_new_handler(&OnNoMemory); |
951 } | 943 } |
952 | 944 |
953 bool EnableInProcessStackDumping() { | 945 bool EnableInProcessStackDumping() { |
954 // Add stack dumping support on exception on windows. Similar to OS_POSIX | 946 // Add stack dumping support on exception on windows. Similar to OS_POSIX |
955 // signal() handling in process_util_posix.cc. | 947 // signal() handling in process_util_posix.cc. |
956 g_previous_filter = SetUnhandledExceptionFilter(&StackDumpExceptionFilter); | 948 g_previous_filter = SetUnhandledExceptionFilter(&StackDumpExceptionFilter); |
957 AttachToConsole(); | 949 RouteStdioToConsole(); |
958 return true; | 950 return true; |
959 } | 951 } |
960 | 952 |
961 void RaiseProcessToHighPriority() { | 953 void RaiseProcessToHighPriority() { |
962 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); | 954 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); |
963 } | 955 } |
964 | 956 |
965 // GetPerformanceInfo is not available on WIN2K. So we'll | 957 // GetPerformanceInfo is not available on WIN2K. So we'll |
966 // load it on-the-fly. | 958 // load it on-the-fly. |
967 const wchar_t kPsapiDllName[] = L"psapi.dll"; | 959 const wchar_t kPsapiDllName[] = L"psapi.dll"; |
(...skipping 27 matching lines...) Expand all Loading... |
995 | 987 |
996 PERFORMANCE_INFORMATION info; | 988 PERFORMANCE_INFORMATION info; |
997 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { | 989 if (!InternalGetPerformanceInfo(&info, sizeof(info))) { |
998 DLOG(ERROR) << "Failed to fetch internal performance info."; | 990 DLOG(ERROR) << "Failed to fetch internal performance info."; |
999 return 0; | 991 return 0; |
1000 } | 992 } |
1001 return (info.CommitTotal * system_info.dwPageSize) / 1024; | 993 return (info.CommitTotal * system_info.dwPageSize) / 1024; |
1002 } | 994 } |
1003 | 995 |
1004 } // namespace base | 996 } // namespace base |
OLD | NEW |