OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "net/test/test_server.h" | 5 #include "net/test/test_server.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <wincrypt.h> | 8 #include <wincrypt.h> |
9 | 9 |
10 #include "base/base_paths.h" | 10 #include "base/base_paths.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
17 #include "base/test/test_timeouts.h" | 17 #include "base/test/test_timeouts.h" |
18 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
19 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
20 #include "base/win/scoped_handle.h" | 20 #include "base/win/scoped_handle.h" |
21 | 21 |
22 #pragma comment(lib, "crypt32.lib") | 22 #pragma comment(lib, "crypt32.lib") |
23 | 23 |
24 namespace { | 24 namespace { |
25 | 25 |
26 bool LaunchTestServerAsJob(const CommandLine& cmdline, | |
27 bool start_hidden, | |
28 base::ProcessHandle* process_handle, | |
29 base::win::ScopedHandle* job_handle) { | |
30 // Launch test server process. | |
31 STARTUPINFO startup_info = {0}; | |
32 startup_info.cb = sizeof(startup_info); | |
33 startup_info.dwFlags = STARTF_USESHOWWINDOW; | |
34 startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW; | |
35 PROCESS_INFORMATION process_info; | |
36 | |
37 // If this code is run under a debugger, the test server process is | |
38 // automatically associated with a job object created by the debugger. | |
39 // The CREATE_BREAKAWAY_FROM_JOB flag is used to prevent this. | |
40 if (!CreateProcess( | |
41 NULL, const_cast<wchar_t*>(cmdline.GetCommandLineString().c_str()), | |
42 NULL, NULL, TRUE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, | |
43 &startup_info, &process_info)) { | |
44 LOG(ERROR) << "Could not create process."; | |
45 return false; | |
46 } | |
47 CloseHandle(process_info.hThread); | |
48 | |
49 // If the caller wants the process handle, we won't close it. | |
50 if (process_handle) { | |
51 *process_handle = process_info.hProcess; | |
52 } else { | |
53 CloseHandle(process_info.hProcess); | |
54 } | |
55 | |
56 // Create a JobObject and associate the test server process with it. | |
57 job_handle->Set(CreateJobObject(NULL, NULL)); | |
58 if (!job_handle->IsValid()) { | |
59 LOG(ERROR) << "Could not create JobObject."; | |
60 return false; | |
61 } else { | |
62 JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0}; | |
63 limit_info.BasicLimitInformation.LimitFlags = | |
64 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; | |
65 if (0 == SetInformationJobObject(job_handle->Get(), | |
66 JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info))) { | |
67 LOG(ERROR) << "Could not SetInformationJobObject."; | |
68 return false; | |
69 } | |
70 if (0 == AssignProcessToJobObject(job_handle->Get(), | |
71 process_info.hProcess)) { | |
72 LOG(ERROR) << "Could not AssignProcessToObject."; | |
73 return false; | |
74 } | |
75 } | |
76 return true; | |
77 } | |
78 | |
79 // Writes |size| bytes to |handle| and sets |*unblocked| to true. | 26 // Writes |size| bytes to |handle| and sets |*unblocked| to true. |
80 // Used as a crude timeout mechanism by ReadData(). | 27 // Used as a crude timeout mechanism by ReadData(). |
81 void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) { | 28 void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) { |
82 std::string unblock_data(size, '\0'); | 29 std::string unblock_data(size, '\0'); |
83 // Unblock the ReadFile in TestServer::WaitToStart by writing to the pipe. | 30 // Unblock the ReadFile in TestServer::WaitToStart by writing to the pipe. |
84 // Make sure the call succeeded, otherwise we are very likely to hang. | 31 // Make sure the call succeeded, otherwise we are very likely to hang. |
85 DWORD bytes_written = 0; | 32 DWORD bytes_written = 0; |
86 LOG(WARNING) << "Timeout reached; unblocking pipe by writing " | 33 LOG(WARNING) << "Timeout reached; unblocking pipe by writing " |
87 << size << " bytes"; | 34 << size << " bytes"; |
88 CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written, | 35 CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 // | 119 // |
173 // "64-bit versions of Windows use 32-bit handles for | 120 // "64-bit versions of Windows use 32-bit handles for |
174 // interoperability. When sharing a handle between 32-bit and 64-bit | 121 // interoperability. When sharing a handle between 32-bit and 64-bit |
175 // applications, only the lower 32 bits are significant, so it is | 122 // applications, only the lower 32 bits are significant, so it is |
176 // safe to truncate the handle (when passing it from 64-bit to | 123 // safe to truncate the handle (when passing it from 64-bit to |
177 // 32-bit) or sign-extend the handle (when passing it from 32-bit to | 124 // 32-bit) or sign-extend the handle (when passing it from 32-bit to |
178 // 64-bit)." | 125 // 64-bit)." |
179 python_command.AppendArg("--startup-pipe=" + | 126 python_command.AppendArg("--startup-pipe=" + |
180 base::IntToString(reinterpret_cast<uintptr_t>(child_write))); | 127 base::IntToString(reinterpret_cast<uintptr_t>(child_write))); |
181 | 128 |
182 if (!LaunchTestServerAsJob(python_command, | 129 base::LaunchOptions launch_options; |
183 true, | 130 launch_options.inherit_handles = true; |
184 &process_handle_, | 131 launch_options.job_handle = &job_handle_; |
185 &job_handle_)) { | 132 if (!base::LaunchProcess(python_command, launch_options, &process_handle_)) { |
186 LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); | 133 LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); |
187 return false; | 134 return false; |
188 } | 135 } |
189 | 136 |
190 return true; | 137 return true; |
191 } | 138 } |
192 | 139 |
193 bool TestServer::WaitToStart() { | 140 bool TestServer::WaitToStart() { |
194 base::win::ScopedHandle read_fd(child_read_fd_.Take()); | 141 base::win::ScopedHandle read_fd(child_read_fd_.Take()); |
195 base::win::ScopedHandle write_fd(child_write_fd_.Take()); | 142 base::win::ScopedHandle write_fd(child_write_fd_.Take()); |
(...skipping 14 matching lines...) Expand all Loading... |
210 | 157 |
211 if (!ParseServerData(server_data)) { | 158 if (!ParseServerData(server_data)) { |
212 LOG(ERROR) << "Could not parse server_data: " << server_data; | 159 LOG(ERROR) << "Could not parse server_data: " << server_data; |
213 return false; | 160 return false; |
214 } | 161 } |
215 | 162 |
216 return true; | 163 return true; |
217 } | 164 } |
218 | 165 |
219 } // namespace net | 166 } // namespace net |
OLD | NEW |