Holy cow, I wrote a book!
If you're debugging a performance problem in your application,
you may run across a critical section in a very strange state:
A lot of threads are waiting for it, but nobody owns it!
0:000> !critsec 0x10009C70
CritSec at 0x10009C70
This state means that the previous owner of the critical section
has just exited it and signalled a waiting thread to take it,
but that thread hasn't yet gotten a chance to run yet.
This is normally a transient condition,
but if you see it a lot, then you very likely the victim of a
about lock convoys,
so I'm just going to refer you to them to get the details.
Internally, a critical section is a bunch of counters and flags,
and possibly an event.
(Note that the internal structure of a critical section is subject
to change at any time—in fact, it changed between
Windows XP and Windows 2003.
The information provided here is therefore intended for troubleshooting
and debugging purposes and not for production use.)
As long as there is no contention, the counters and flags are
sufficient because nobody has had to wait for the critical section
(and therefore nobody had to be woken up when the critical section
If a thread needs to be blocked because the critical section it wants
is already owned by another thread,
the kernel creates an event for the critical section
(if there isn't one already) and waits on it.
When the owner of the critical section finally releases it,
the event is signaled, thereby alerting all the waiters that the
critical section is now available and they should try to enter it
(If there is more than one waiter, then only one will actually
enter the critical section and the others will return to the wait
If you get an invalid handle exception in
it means that the critical section code thought that there
were other threads waiting for the critical section to become
available, so it tried to signal the event, but the event handle
was no good.
Now you get to use your brain to come up with reasons why this might be.
One possibility is that the critical section has been corrupted,
and the memory that normally holds the event handle has been
overwritten with some other value that happens not to be a
Another possibility is that some other piece of code passed
an uninitialized variable to the CloseHandle
function and ended up closing the critical section's handle
This can also happen if some other piece of code has a double-close
bug, and the handle (now closed) just happened to be reused as the
critical section's event handle.
When the buggy code closes the handle the second time by mistake,
it ends up closing the critical section's handle instead.
Of course, the problem might be that the critical section is not
valid because it was never initialized in the first place.
The values in the fields are just uninitialized garbage,
and when you try to leave this uninitialized critical section,
that garbage gets used as an event handle, raising the invalid
Then again, the problem might be that the critical section is
not valid because it has already been destroyed.
For example, one thread might have code that goes like this:
... do stuff...
While that thread is busy doing stuff,
another thread calls
This destroys the critical section while another thread
was still using it.
Eventually that thread finishes doing its stuff and calls
which raises the invalid handle exception because the
DeleteCriticalSection already closed the handle.
All of these are possible reasons for an invalid handle
exception in LeaveCriticalSection.
To determine which one you're running into will require more
debugging, but at least now you know what to be looking for.
One of my colleagues from the kernel team points out that
the Locks and Handles checks in
Application Verifier are great
for debugging issues like this.
Manufacturer of commercial and home blenders Blendtec
has produced a marketing web site
Will It Blend? which features short videos of the
Internet blending icon
throwing all sorts of unusual objects
into one of their blenders, to see what happens.
(The videos are also on YouTube,
and of course they have a blog, cleverly titled
Will it Blog?)
a miniature profile of Tom Dickson
in Utah Business Magazine.
When Jamba Juice told Dickson the $14,000 blender package was too expensive,
he cut them a deal, asking simply for a nickel of every sale.
Now, with 50 million smoothies sold each year,
Dickson says it was one of the best deals he ever made.
"Will It Blend?" is sort of a blender-themed entry in the style of
David Letterman's crowd-pleasing stunts such as
"Throwing things off the roof,"
"Crushing things in a pneumatic press," and
"Will it Float?"
(I suspect that only guys find this stuff fascinating.)
One of the more subtle ways
people mess up IUnknown::QueryInterface
when the problem wasn't actually an unsupported interface.
E_NOINTERFACE return value
has very specific meaning.
Do not use it as your generic "gosh, something went wrong" error.
(Use an appropriate error such as E_OUTOFMEMORY
Recall that the rules for
are that (in the absence of catastrophic errors such as
if a request for a particular interface succeeds,
then it must always succeed in the future for that object.
Similarly, if a request fails with E_NOINTERFACE,
then it must always fail in the future for that object.
These rules exist for a reason.
In the case where COM needs to create a proxy for your object
(for example, to marshal the object into a different apartment),
the COM infrastructure does a lot of interface caching (and
negative caching) for performance reasons.
For example, if a request for an interface fails, COM remembers
this so that future requests for that interface are failed
immediately rather than being marshalled to the original object
only to have the request fail anyway.
Requests for unsupported interfaces are very common in COM,
and optimizing that case yields significant performance improvements.
If you start returning E_NOINTERFACE for problems
other than "The object doesn't support this interface",
COM will assume that the object really doesn't support the interface
and may not ask for it again even if you do.
This in turn leads to very strange bugs that defy debugging:
You are at a call to
you set a breakpoint on your object's implementation of
IUnknown::QueryInterface to see what the problem is,
you step over the call and get
E_NOINTERFACE back without your breakpoint ever hitting.
Because at some point in the past, you said you didn't support
the interface, and COM remembered this and "saved you the trouble"
of having to respond to a question you already answered.
The COM folks tell me that they and their comrades in product support
end up spending hours debugging customer's problems like
"When my computer is under load, sometimes I start getting
E_NOINTERFACE for interfaces I definitely support."
Save yourself and the COM folks several hours of frustration.
Don't return E_NOINTERFACE
unless you really mean it.
Back in 2003, I wrote that
I'm doing this instead of writing a book.
That was true then, but last year I decided to give this book thing
another go, only to find that publishers generally aren't interested
in this stuff any more.
"Does the world really need another book on Win32?
Nobody buys Win32 books any more, that dinosaur!"
"A conversational style book?
People want books with step-by-step how-to's and comprehensive treatments,
not water cooler anecdotes!"
"Just 200 pages?
There isn't enough of an audience for a book that small!"
Luckily, I found a sympathetic ear from the folks at
who were willing to take a chance on my unorthodox proposal.
But I caved on the length, bringing it up to 500 pages.
Actually, I came up with more like 700 pages of stuff,
and they cut it back to 500,
because 700 pages would take the book into the next price tier, and
"There isn't enough of an audience for a book that big!"
Eighteen months later, we have
The Old New Thing:
Practical Development Throughout the Evolution of Windows,
following in what appears to be the current fad of giving your
book a title of the form
Catchy Phrase: Longer Explanation of What the Catchy Phrase Means.
It's a selection of entries from this blog,
and with new material sprinkled in.
There are also new chapters that go in depth into parts of Win32
you use every day but may not fully understand
(the dialog manager, window messages), plus a chapter dedicated
(For some reason, the Table of Contents on the book web site is incomplete.)
Oh, and those 200 pages that got cut?
They'll be made available for download as "bonus chapters".
(The bonus chapters aren't up yet, so don't all rush over there
looking for them.)
The nominal release date for the book is January 2007,
which is roughly in agreement with the book web site
which proclaims availability on December 29th.
Just in time for Christmas your favorite geek,
if your favorite geek can't read a calendar.
Now I get to see
how many people were lying
when they said, "If you wrote a book based on this blog, I'd buy it."
The bonus chapters are now available.)
Now available in Japanese!
Now available in Chinese!
Here are more sentences from seventh grade time travel essays.
Remember, these sentences are not representative of seventh grade
writing in general;
these are just the funny bits.
Letter Format: Some students took advantage of the fact that
the essay took the form of a letter.
Here's a question that floated past my view:
How do I set the ACLs on a file so users can read it
but can't copy it?
I can't find a "Copy" access mask that I can deny.
If I can't deny copying, I'd at least like to audit it,
so I can tell who made a copy of the file.
There is no "Copy" access mask because copying is not
a fundamental file operation.
Copying a file is just reading it into memory and then
writing it out.
Once the bytes come off the disk, the file system has no
control any more over what the user does with them.
(Make sure you've read
Part 1 for background information.)
On the subject of where they would go in a time machine,
many students wrote well-thought-out essays,
These sentences below did not come from those essays.
I've categorized the snippets roughly by theme,
though I had to guess at some of them since the sentences are taken
out of context.
(In a futile attempt to assist non-native speakers,
I have glossed some of the trickier parts.
I've also added editorial comments in italics.)
Personal History: These are essays from students who would
travel to their own past.
The Middle Ages:
The students recently studied the Middle Ages,
which helps to explain why so many of them chose to go there.
United States(?) History
I'll stop here before I
runnun too much.
We'll learn more about seventh graders and time machines in
the next installment.
You already know how to do this,
you just don't realize it.
How do you find files with an "x" in their name?
That's right, you use dir *x*.
Now you just have to change that x to a space.
And since spaces are command line delimiters, you need to quote
the sequence so it gets treated as a single parameter
rather than two "*" parameters:
dir "* *"
Stick in a /s if you want to search recursively.
All the students at a local school
were asked to composed an in-class essay on the following topic:
"Your science teacher has invented a time machine.
You have been selected to take the first trip.
Explain in a multi-paragraph letter to your teacher
where you will go and why."
(Students were given two hours, plus one additional hour upon request.
In practice, many students were finished early and
almost nobody requested the third hour.)
(Aside: Sometimes I think my readers believe in time machines.
For example, one of them wondered
why OLE/COM uses HRESULTs instead of Win32 error codes.
Um, when OLE was invented, Win32 didn't exist.)
The students really enjoyed this topic.
Too much so, however,
for more than a few of them turned their essays into a narrative
rather than sticking to the assignment.
One student was so excited that the essay consisted of a single
Well, technically it was two paragraphs,
thereby meeting the letter (if not the spirit)
of the "multi-paragraph" requirement.
About halfway down page three was this sentence:
"The essay continues in the next paragraph."
Roughly two thirds of the students opted to go into the past;
one third chose to go into the future.
One student didn't travel in time at all (!),
choosing instead to visit Europe in the present day
"to see castles and ruins".
Psst, you've got a time machine.
Why not go and see the ruins before they are ruined?
(Actually, some friends pointed out to me that travelling to the present
day is still handy.
You can use your time machine as a teleporter.
And you can even set the time machine to zip you backward, say,
That way, when you travel from Seattle to Europe,
you arrive without any jet lag!)
Boys were more likely to want to travel back in time to get rich,
although their plans for doing so were not necessarily fully thought-out.
(Good luck getting anybody in the past to accept today's money.)
Girls were more likely to travel in time to meet themselves or
A few students confused a time machine with regressive therapy,
choosing to go back in time to re-live a cherished moment from
a year or two ago.
Psst, if you use a time machine to go into the past to visit
yourself on that awesome vacation to Hawaii,
you won't re-live the vacation.
You'll be watching the other copy of yourself enjoy the vacation.
assuming that the other copy of yourself doesn't see you and freak out.)
Several students wanted to change world history.
Many students wanted to go back in time to observe and experience
a historical period.
One student wanted to ask Jesus to teach him how to walk on water.
(Step one: Be the son of God.)
Coming up in Part 2,
selected sentences from student essays.
Where would you go if you could take one trip in a time machine?