Today on the Coverity Development Testing Blog’s continuing series Ask The Bug Guys I’ll discuss why it is that two delegates that look the same are not actually assignment compatible, and how to work around this restriction. Continue reading
Monthly Archives: June 2014
Real world async/await defects
Today I’m once again asking for your help.
The headliner feature for C# 5 was of course the await operator for asynchronous methods. The intention of the feature was to make it easier to write asynchronous programs where the program text is not a mass of inside-out code that emphasizes the mechanisms of asynchrony, but rather straightforward, easy-to-read code; the compiler can deal with the mess of turning the code into a form of continuation passing style.
However, asynchrony is still hard to understand, and making methods that allow other code to run before their postconditions are met makes for all manner of interesting possible bugs. There are a lot of great articles out there giving good advice on how to avoid some of the pitfalls, such as:
- Psychic debugging of async methods
- Pitfalls to avoid when passing async lambdas
- Async gotchas
- Don’t mix await and compound assignment
- Don’t block on async code
These are all great advice, but it is not always clear which of these potential defects are merely theoretical, and which you have seen and fixed in actual production code. That’s what I am very interested to learn from you all: what mistakes were made by real people, how were they discovered, and what was the fix?
Here’s an example of what I mean. This defect was found in real-world code; obviously the extraneous details have been removed:
Frob GetFrob() { Frob result = null; var networkDevice = new NetworkDevice(); networkDevice.OnDownload += async (state) => { result = await Frob.DeserializeStateAsync(state); }; networkDevice.GetSerializedState(); // Synchronous return result; }
The network device synchronously downloads the serialized state of a Frob
. When it is done, the delegate stored in OnDownload
runs synchronously, and is passed the state that was just downloaded. But since it is itself asynchronous, the event handler starts deserializing the state asynchronously, and returns immediately. We now have a race between GetFrob
returning null, and the mutation of closed-over local result
, a race almost certainly won by returning null.
If you’d rather not leave comments here — and frankly, the comment system isn’t much good for code snippets anyways — feel free to email me at eric@lippert.com
. If I get some good examples I’ll follow up with a post describing the defects.
London and Budapest
I recently spent a week visiting customers and giving talks in Europe and holy goodness, never have I been in so many countries in so little time. I flew from Seattle to London, changed planes, flew to Amsterdam, visited customers in the Netherlands and Belgium, then took the Eurostar from Lille back to London, and that was just the first two days! Continue reading
ATBG: Why do enumerators avoid a bounds check?
I am back from a week in which I visited England, Holland, Belgium, France and Hungary; this is by far the most countries I’ve been to in so little time. It was great to meet so many customers; more on bicycling around Budapest in a future episode. For today though, I’ve posted on the Coverity Development Testing Blog’s continuing series Ask The Bug Guys a follow up to the previous episode. I’ll discuss why the struct-based list enumerator does not do bounds checking in its implementation of the Current
property. Check it out! Thanks to reader Xi Chen for the question. Continue reading