OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "tools/gn/input_file_manager.h" | 5 #include "tools/gn/input_file_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "tools/gn/filesystem_utils.h" | 9 #include "tools/gn/filesystem_utils.h" |
10 #include "tools/gn/parser.h" | 10 #include "tools/gn/parser.h" |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 { | 208 { |
209 base::AutoUnlock unlock(lock_); | 209 base::AutoUnlock unlock(lock_); |
210 data->completion_event->Wait(); | 210 data->completion_event->Wait(); |
211 } | 211 } |
212 // If there were multiple waiters on the same event, we now need to wake | 212 // If there were multiple waiters on the same event, we now need to wake |
213 // up the next one. | 213 // up the next one. |
214 data->completion_event->Signal(); | 214 data->completion_event->Signal(); |
215 } | 215 } |
216 } | 216 } |
217 | 217 |
218 // The other load could have failed. In this case that error will be printed | 218 // The other load could have failed. In this case that error was probably |
219 // to the console, but we need to return something here, so make up a | 219 // printed to the console, but we need to return something here, so make up a |
220 // dummy error. | 220 // dummy error. |
221 if (!data->parsed_root) | 221 // |
222 *err = Err(origin, "File parse failed"); | 222 // There is a race condition. The other load could have failed, but if the |
| 223 // other thread is delayed for some reason, this thread could end up |
| 224 // reporting the error to the scheduler first (since first error report |
| 225 // wins). The user will see this one and the "real" one will be discarded. |
| 226 if (!data->parsed_root) { |
| 227 *err = Err(origin, "File parse failed.", |
| 228 "If you see this, I'm really sorry, but a race condition has caused\n" |
| 229 "me to eat your error message. It was crunchy. If the parse error\n" |
| 230 "in your imported file isn't obvious, try re-running GN."); |
| 231 } |
223 return data->parsed_root.get(); | 232 return data->parsed_root.get(); |
224 } | 233 } |
225 | 234 |
226 void InputFileManager::AddDynamicInput(const SourceFile& name, | 235 void InputFileManager::AddDynamicInput(const SourceFile& name, |
227 InputFile** file, | 236 InputFile** file, |
228 std::vector<Token>** tokens, | 237 std::vector<Token>** tokens, |
229 scoped_ptr<ParseNode>** parse_root) { | 238 scoped_ptr<ParseNode>** parse_root) { |
230 InputFileData* data = new InputFileData(name); | 239 InputFileData* data = new InputFileData(name); |
231 { | 240 { |
232 base::AutoLock lock(lock_); | 241 base::AutoLock lock(lock_); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 | 318 |
310 // Run pending invocations. Theoretically we could schedule each of these | 319 // Run pending invocations. Theoretically we could schedule each of these |
311 // separately to get some parallelism. But normally there will only be one | 320 // separately to get some parallelism. But normally there will only be one |
312 // item in the list, so that's extra overhead and complexity for no gain. | 321 // item in the list, so that's extra overhead and complexity for no gain. |
313 if (success) { | 322 if (success) { |
314 for (size_t i = 0; i < callbacks.size(); i++) | 323 for (size_t i = 0; i < callbacks.size(); i++) |
315 callbacks[i].Run(unowned_root); | 324 callbacks[i].Run(unowned_root); |
316 } | 325 } |
317 return success; | 326 return success; |
318 } | 327 } |
OLD | NEW |