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 "net/test/spawned_test_server/local_test_server.h" | 5 #include "net/test/spawned_test_server/local_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" |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 // Writes |size| bytes to |handle| and sets |*unblocked| to true. | 30 // Writes |size| bytes to |handle| and sets |*unblocked| to true. |
31 // Used as a crude timeout mechanism by ReadData(). | 31 // Used as a crude timeout mechanism by ReadData(). |
32 void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) { | 32 void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) { |
33 std::string unblock_data(size, '\0'); | 33 std::string unblock_data(size, '\0'); |
34 // Unblock the ReadFile in LocalTestServer::WaitToStart by writing to the | 34 // Unblock the ReadFile in LocalTestServer::WaitToStart by writing to the |
35 // pipe. Make sure the call succeeded, otherwise we are very likely to hang. | 35 // pipe. Make sure the call succeeded, otherwise we are very likely to hang. |
36 DWORD bytes_written = 0; | 36 DWORD bytes_written = 0; |
37 LOG(WARNING) << "Timeout reached; unblocking pipe by writing " | 37 LOG(WARNING) << "Timeout reached; unblocking pipe by writing " << size |
38 << size << " bytes"; | 38 << " bytes"; |
39 CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written, | 39 CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written, NULL)); |
40 NULL)); | |
41 CHECK_EQ(size, bytes_written); | 40 CHECK_EQ(size, bytes_written); |
42 *unblocked = true; | 41 *unblocked = true; |
43 } | 42 } |
44 | 43 |
45 // Given a file handle, reads into |buffer| until |bytes_max| bytes | 44 // Given a file handle, reads into |buffer| until |bytes_max| bytes |
46 // has been read or an error has been encountered. Returns | 45 // has been read or an error has been encountered. Returns |
47 // true if the read was successful. | 46 // true if the read was successful. |
48 bool ReadData(HANDLE read_fd, HANDLE write_fd, | 47 bool ReadData(HANDLE read_fd, HANDLE write_fd, DWORD bytes_max, uint8* buffer) { |
49 DWORD bytes_max, uint8* buffer) { | |
50 base::Thread thread("test_server_watcher"); | 48 base::Thread thread("test_server_watcher"); |
51 if (!thread.Start()) | 49 if (!thread.Start()) |
52 return false; | 50 return false; |
53 | 51 |
54 // Prepare a timeout in case the server fails to start. | 52 // Prepare a timeout in case the server fails to start. |
55 bool unblocked = false; | 53 bool unblocked = false; |
56 thread.message_loop()->PostDelayedTask( | 54 thread.message_loop()->PostDelayedTask( |
57 FROM_HERE, base::Bind(UnblockPipe, write_fd, bytes_max, &unblocked), | 55 FROM_HERE, |
| 56 base::Bind(UnblockPipe, write_fd, bytes_max, &unblocked), |
58 TestTimeouts::action_max_timeout()); | 57 TestTimeouts::action_max_timeout()); |
59 | 58 |
60 DWORD bytes_read = 0; | 59 DWORD bytes_read = 0; |
61 while (bytes_read < bytes_max) { | 60 while (bytes_read < bytes_max) { |
62 DWORD num_bytes; | 61 DWORD num_bytes; |
63 if (!ReadFile(read_fd, buffer + bytes_read, bytes_max - bytes_read, | 62 if (!ReadFile(read_fd, |
64 &num_bytes, NULL)) { | 63 buffer + bytes_read, |
| 64 bytes_max - bytes_read, |
| 65 &num_bytes, |
| 66 NULL)) { |
65 PLOG(ERROR) << "ReadFile failed"; | 67 PLOG(ERROR) << "ReadFile failed"; |
66 return false; | 68 return false; |
67 } | 69 } |
68 if (num_bytes <= 0) { | 70 if (num_bytes <= 0) { |
69 LOG(ERROR) << "ReadFile returned invalid byte count: " << num_bytes; | 71 LOG(ERROR) << "ReadFile returned invalid byte count: " << num_bytes; |
70 return false; | 72 return false; |
71 } | 73 } |
72 bytes_read += num_bytes; | 74 bytes_read += num_bytes; |
73 } | 75 } |
74 | 76 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 // variables more easily. | 109 // variables more easily. |
108 scoped_ptr<base::Environment> environment_; | 110 scoped_ptr<base::Environment> environment_; |
109 | 111 |
110 // A flag saying if we have actually modified the environment. | 112 // A flag saying if we have actually modified the environment. |
111 bool path_modified_; | 113 bool path_modified_; |
112 | 114 |
113 DISALLOW_COPY_AND_ASSIGN(ScopedPath); | 115 DISALLOW_COPY_AND_ASSIGN(ScopedPath); |
114 }; | 116 }; |
115 | 117 |
116 ScopedPath::ScopedPath(const base::FilePath& path_to_add) | 118 ScopedPath::ScopedPath(const base::FilePath& path_to_add) |
117 : environment_(base::Environment::Create()), | 119 : environment_(base::Environment::Create()), path_modified_(false) { |
118 path_modified_(false) { | |
119 environment_->GetVar("PATH", &old_path_); | 120 environment_->GetVar("PATH", &old_path_); |
120 | 121 |
121 std::string new_value = old_path_; | 122 std::string new_value = old_path_; |
122 if (!new_value.empty()) | 123 if (!new_value.empty()) |
123 new_value += ";"; | 124 new_value += ";"; |
124 | 125 |
125 new_value += base::WideToUTF8(path_to_add.value()); | 126 new_value += base::WideToUTF8(path_to_add.value()); |
126 | 127 |
127 path_modified_ = environment_->SetVar("PATH", new_value); | 128 path_modified_ = environment_->SetVar("PATH", new_value); |
128 } | 129 } |
(...skipping 23 matching lines...) Expand all Loading... |
152 HANDLE child_read = NULL; | 153 HANDLE child_read = NULL; |
153 HANDLE child_write = NULL; | 154 HANDLE child_write = NULL; |
154 if (!CreatePipe(&child_read, &child_write, NULL, 0)) { | 155 if (!CreatePipe(&child_read, &child_write, NULL, 0)) { |
155 PLOG(ERROR) << "Failed to create pipe"; | 156 PLOG(ERROR) << "Failed to create pipe"; |
156 return false; | 157 return false; |
157 } | 158 } |
158 child_read_fd_.Set(child_read); | 159 child_read_fd_.Set(child_read); |
159 child_write_fd_.Set(child_write); | 160 child_write_fd_.Set(child_write); |
160 | 161 |
161 // Have the child inherit the write half. | 162 // Have the child inherit the write half. |
162 if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT, | 163 if (!SetHandleInformation( |
163 HANDLE_FLAG_INHERIT)) { | 164 child_write, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { |
164 PLOG(ERROR) << "Failed to enable pipe inheritance"; | 165 PLOG(ERROR) << "Failed to enable pipe inheritance"; |
165 return false; | 166 return false; |
166 } | 167 } |
167 | 168 |
168 // Pass the handle on the command-line. Although HANDLE is a | 169 // Pass the handle on the command-line. Although HANDLE is a |
169 // pointer, truncating it on 64-bit machines is okay. See | 170 // pointer, truncating it on 64-bit machines is okay. See |
170 // http://msdn.microsoft.com/en-us/library/aa384203.aspx | 171 // http://msdn.microsoft.com/en-us/library/aa384203.aspx |
171 // | 172 // |
172 // "64-bit versions of Windows use 32-bit handles for | 173 // "64-bit versions of Windows use 32-bit handles for |
173 // interoperability. When sharing a handle between 32-bit and 64-bit | 174 // interoperability. When sharing a handle between 32-bit and 64-bit |
174 // applications, only the lower 32 bits are significant, so it is | 175 // applications, only the lower 32 bits are significant, so it is |
175 // safe to truncate the handle (when passing it from 64-bit to | 176 // safe to truncate the handle (when passing it from 64-bit to |
176 // 32-bit) or sign-extend the handle (when passing it from 32-bit to | 177 // 32-bit) or sign-extend the handle (when passing it from 32-bit to |
177 // 64-bit)." | 178 // 64-bit)." |
178 python_command.AppendArg("--startup-pipe=" + | 179 python_command.AppendArg( |
| 180 "--startup-pipe=" + |
179 base::IntToString(reinterpret_cast<uintptr_t>(child_write))); | 181 base::IntToString(reinterpret_cast<uintptr_t>(child_write))); |
180 | 182 |
181 job_handle_.Set(CreateJobObject(NULL, NULL)); | 183 job_handle_.Set(CreateJobObject(NULL, NULL)); |
182 if (!job_handle_.IsValid()) { | 184 if (!job_handle_.IsValid()) { |
183 LOG(ERROR) << "Could not create JobObject."; | 185 LOG(ERROR) << "Could not create JobObject."; |
184 return false; | 186 return false; |
185 } | 187 } |
186 | 188 |
187 if (!base::SetJobObjectLimitFlags(job_handle_.Get(), | 189 if (!base::SetJobObjectLimitFlags(job_handle_.Get(), |
188 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)) { | 190 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)) { |
(...skipping 10 matching lines...) Expand all Loading... |
199 } | 201 } |
200 | 202 |
201 return true; | 203 return true; |
202 } | 204 } |
203 | 205 |
204 bool LocalTestServer::WaitToStart() { | 206 bool LocalTestServer::WaitToStart() { |
205 base::win::ScopedHandle read_fd(child_read_fd_.Take()); | 207 base::win::ScopedHandle read_fd(child_read_fd_.Take()); |
206 base::win::ScopedHandle write_fd(child_write_fd_.Take()); | 208 base::win::ScopedHandle write_fd(child_write_fd_.Take()); |
207 | 209 |
208 uint32 server_data_len = 0; | 210 uint32 server_data_len = 0; |
209 if (!ReadData(read_fd.Get(), write_fd.Get(), sizeof(server_data_len), | 211 if (!ReadData(read_fd.Get(), |
| 212 write_fd.Get(), |
| 213 sizeof(server_data_len), |
210 reinterpret_cast<uint8*>(&server_data_len))) { | 214 reinterpret_cast<uint8*>(&server_data_len))) { |
211 LOG(ERROR) << "Could not read server_data_len"; | 215 LOG(ERROR) << "Could not read server_data_len"; |
212 return false; | 216 return false; |
213 } | 217 } |
214 std::string server_data(server_data_len, '\0'); | 218 std::string server_data(server_data_len, '\0'); |
215 if (!ReadData(read_fd.Get(), write_fd.Get(), server_data_len, | 219 if (!ReadData(read_fd.Get(), |
| 220 write_fd.Get(), |
| 221 server_data_len, |
216 reinterpret_cast<uint8*>(&server_data[0]))) { | 222 reinterpret_cast<uint8*>(&server_data[0]))) { |
217 LOG(ERROR) << "Could not read server_data (" << server_data_len | 223 LOG(ERROR) << "Could not read server_data (" << server_data_len |
218 << " bytes)"; | 224 << " bytes)"; |
219 return false; | 225 return false; |
220 } | 226 } |
221 | 227 |
222 if (!ParseServerData(server_data)) { | 228 if (!ParseServerData(server_data)) { |
223 LOG(ERROR) << "Could not parse server_data: " << server_data; | 229 LOG(ERROR) << "Could not parse server_data: " << server_data; |
224 return false; | 230 return false; |
225 } | 231 } |
226 | 232 |
227 return true; | 233 return true; |
228 } | 234 } |
229 | 235 |
230 } // namespace net | 236 } // namespace net |
231 | |
OLD | NEW |