This is the second post in a series about bugs you can’t avoid, can’t predict, and can’t even diagnose without significant time investment. Bugs that aren’t your fault, because they are in your tools. The bane of time estimates and deadlines, the unfathomable bug.
Today’s bug comes courtesy of Microsoft. Thank you, Microsoft, this series wouldn’t exist without the generous support of entities like you.
After diagnosing and avoiding the triply nested namespaces bug, I was feeling quite pleased with myself. The project built, started, ran … and promptly died after five seconds.
The problem appeared simple. The crash occurred during file IO, and I noticed the code was not using the WinRT API. Probably something one of my fellow programmers found on the web when trying to do synchronous IO. It worked fine before, but maybe Microsoft tightened the rules for Windows 8 RTM (the IO API in WinRT is entirely asynchronous). I rewrote the offending code to do things the “right” way (but cheated a little by blocking on the async results).
Naturally, being unfathomable, the crash didn’t go away. My next guess was that the file wasn’t present, due to a recent merge resolution error or other minor mistake. Indeed, some files being asked for were not present, but in each case it was clear that this was intentional (the caller explicitly checked if the load succeeded or not). More importantly, the crash still occurred even when the file did exist.
I tried more things. Suffice it to say that they became more and more absurd, because the real problem was so unbelievably stupid. I really feel that I can’t do it justice so… just… here’s the fix:
- var file = await root.GetFileAsync(path); + var file = await root.GetFileAsync(path.Replace("/", "\\"));
Some of the file IO methods don’t handle the alternate directory character (‘/’ instead of ‘\’) correctly. The file IO methods in WinRT. An API by Microsoft. For Windows. Where it is universally expected that both forward and backward slashes are directory separators.
What. The. F-
Don’t believe me? Try it for yourself. Create a new C# windows store project, and put the following code inside the OnNavigatedTo function in MainPage.xaml.cs (or anywhere else where it runs when you start the project):
var root = Windows.ApplicationModel.Package.Current.InstalledLocation; var t1 = root.GetFileAsync("Assets\\Logo.png").AsTask(); var t2 = root.GetFileAsync("Assets/Logo.png").AsTask(); t1.Wait(); // works fine, task succeeded t2.Wait(); // ERROR
Twisted Oak Studios offers consulting and development on high-tech interactive projects. Check out our portfolio, or Give us a shout if you have anything you think some really rad engineers should help you with.
- Eventual Exceptions vs Programming in a Minimal Functional Style
- The Mystery of Flunf
- Explain it like I’m Five: The Socialist Millionaire Problem and Secure Multi-Party Computation
- Computer Science Blows My Mind
- A visit to Execution Labs in Montréal
- Transmuting Dice, Conserving Entropy
- Rule of Thumb: Ask for the Clock
- Rule of Thumb: Use Purposefully Weakened Methods
- Rule of thumb: Preconditions Should be Checked Explicitly
- Intersecting Linked Lists Faster
- Mouse Path Smoothing for Jack Lumber
- My Bug, My Bad #2: Sunk by Float
- Repeat Yourself Differently
- Grover’s Quantum Search Algorithm
- Followup to Non-Nullable Types vs C#
- Optimizing Just in Time with Expression Trees
- When One-Way Latency Doesn’t Matter
- Determining exactly if/when/where a moving line intersected a moving point
- Emulating Actors in C# with Async/Await
- Making an immutable queue with guaranteed constant time operations
- Improving Checked Exceptions
- Perishable Collections: The Benefits of Removal-by-Lifetime
- Decoupling shared control
- Decoupling inlined UI code
- Linq to Collections: Beyond IEnumerable<T>
- Publish your .Net library as a NuGet package
- When null is not enough: an option type for C#
- Unfathomable Bugs #5: Readonly or not
- Minkowski sums: examples
- My Bug, My Bad #1: Fractal Spheres
- Working around the brittle UI Virtualization in Windows 8
- Encapsulating Angles
- Unfathomable Bugs #4: Keys that aren’t
- How would I even use a monad (in C#)?
- Useful/Interesting Methods #1: Observable.WhenEach
- Unfathomable Bugs #3: Stringing you along
- Anonymous Implementation Classes – A Design Pattern for C#
- Tasks for ActionScript 3 – Improving on Event-Driven Programming
- Minkowski sums and differences
- Non-Nullable Types vs C#: Fixing the Billion Dollar Mistake
- Script templates and base classes
- Unity font extraction
- Abusing “Phantom Types” to Encode List Lengths Into Their Type
- Constructive Criticism of the Reactive Extensions API
- Quaternions part 3
- Quaternions part 2
- Quaternions part 1
- Unfathomable Bugs #1: You can have things! You can have things IN things! You can have …
- Coroutines – More than you want to know
- Asset Bundle Helper
- The Visual Studio goes away
- .Net’s time traveling StopWatch
- Introducing Catalyst