| 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 |