During process termination, the gates are now electrified


It turns out that my quick overview of how processes exit on Windows XP was already out of date when I wrote it. Mind you, the information is still accurate for Windows XP (as far as I know), but the rules changed in Windows Vista.

What about critical sections? There is no "Uh-oh" return value for critical sections; EnterCriticalSection doesn't have a return value. Instead, the kernel just says "Open season on critical sections!" I get the mental image of all the gates in a parking garage just opening up and letting anybody in and out.

In Windows Vista, the gates don't go up. Instead they become electrified!

If during DLL_PROCESS_DETACH at process termination on Windows Vista you call EnterCriticalSection on a critical section that has been orphaned, the kernel no longer responds by just letting you through. Instead, it says, "Oh dear, things are in unrecoverably bad shape. Best to just terminate the process now." If you try to enter an orphaned critical section during process shutdown, the kernel simply calls TerminateProcess on the current process!

It's sort of like the movie Speed: If the thread encounters a critical section that causes it to drop below 50 miles per hour, it blows up.

Fortunately, this error doesn't change the underlying analysis of How my lack of understanding of how processes exit on Windows XP forced a security patch to be recalled.

But it also illustrates how the details of process shutdown are open to changes in the implementation at any time, so you shouldn't rely on them. Remember the classical model for how processes exit: You cleanly shut down all your worker threads, and then call ExitProcess. If you don't follow that model (and given the current programming landscape, you pretty have no choice but to abandon that model, what with DLLs creating worker threads behind your back), it's even more important that you follow the general guidance of not doing anything scary in your DllMain function.

Comments (24)
  1. Tom says:

    I’m a little shocked (no pun intended…or is it?) to hear about the electrification of critical sections on process exit.  I can imagine at least one scenario where the forced termination of the process might lead to data corruption in a file.  But I suppose it’s generally better to terminate the application in case something might go wrong than to have an access violation dialog appear when you close the application.

    P.S.  There are two links to the Simpson’s wiki in your article that are broken because they use ‘hef’ instead of ‘href’ in the anchor tags.  I only noticed them because I accidentally bumped my mouse and the pointer hovered over one of the links.

    [Link fixed (I could find only one), thanks. -Raymond]
  2. Médinoc says:

    It’s a shame those DLLs don’t expose a means to clean up their threads. I remember reading something about the CLR, that said .Net solved this problem for CLR threads by marking them with a "strong" or "weak" value, and allowing the process to exit after all "strong" threads had exited. But I don’t rememebr where I read that exactly.

    PS: Also, there’s the problem of COM components failing to properly call SHGetInstanceExplorer() when they create worker threads. Such as Windows’s own ZipFldr.dll, as it seemed when I tried to use it from a console application.

  3. bahbar says:

    Can’t resolve that “simpsonswiki” server here.

    [Looks like the site shut down in 2008. Oh well. -Raymond]
  4. Alexandre Grigoriev says:

    Now, if only Vista on session logout allowed applications to show their “Save: Yes, No, Cancel” dialogs (like XP does), instead of putting that dreaded shadow screen with scary words about a hung application…

    [Now if only people would realize that the topic is a kernel-mode view of how processes terminate, not a discussion of the system shutdown user experience. Oh wait, complaining about Vista is always on-topic around here. -Raymond]
  5. Sinan Unur says:

    Interesting, indeed. Minor correction: s/classical modal/classical model/

    [Fixed, thanks. -Raymond]
  6. Cooney says:

    This reminds me of a boss I had – he basically told a bunch of us to always design apps for exit behavior. I suppose that if you don’t think about it up front, the natural tendency is for process shutdown to resemble a hotel demolition. Now, even more so.

  7. Marquess says:

    While I don’t quite know what you were linking to, the current thing most likely to be called the Simpsons Wiki resides at simpsons.wikia.com. Dunno if that would help.

  8. Ben says:

    @Tom: If an application needs to do work to properly save a file, it should do so before calling ExitProcess() or exiting winmain.  It’s silly to design your system such that your DllMain() handler does mission critical work.

  9. Teo says:

    This is too much off-topic but I’ll try to sneak it anyway. Because I am a back-office guy (think of WMI providers, services, a little kernel-mode programming, stuff like this), when you talk to DllMain and friends I yawn, because there’s nothing new for me to learn. Will you please, please, please consider again writing articles about GUI stuff? I know that you have articles written for months in advance, but maybe you can reschedule something gui-related for publishing sooner. Pretty please?

    [It’s easier writing about non-GUI stuff because when I write GUI stuff people expect to see sample code, and writing sample code is a lot of work. Whereas when I write about non-GUI stuff, I can just talk about code in a more general sense and nobody expects me to write a sample program that illustrates the topic. -Raymond]
  10. Ulrich says:

    Hi,

    do you have any idea why this detail was changed? Was it just a side effect of some other change or a conscientious decision? (A quick guess is that the new way might speed up the termination of not properly coded threads.)

  11. Gabe says:

    Ben: The typical reason for trying saving a file from DllMain is when a DLL needs to write a diagnostic log file. If you write to the file on every function call, you could end up hitting the disk (or network) thousands of times per second, so instead you buffer your log messages and write them to disk only when the buffer is full. The only problem is then to flush the buffer and close the file when your DLL is unloaded.

  12. Teo says:

    It’s sad, but it’s your free time after all. Anyway, even your older posts for the scrollbars and dealing with RDP were useful so I can just go back and re-read them.

  13. Alexandre Grigoriev says:

    @Gabe,

    Just CreateFile with default (cached) mode, and issue WriteFile for each log line. It won’t hit a disk for every call. Bonus point: If you open the file in APPEND mode (pass SYNCHRONIZE|APPEND to CreateFile instead of GENERIC_WRITE), you can write to the same file from separate processes (separate handles) without any synchronization.

  14. Jim Lyon says:

    @Cooney: "He basically told a bunch of us to always design apps for exit behavior."

    This is close to a good idea, but not quite right. Always design for CRASH behavior.

    Once you’ve designed how the user is going to deal with application after a system crash, process exit is easy. You’ll seldom have a good reason to do anything other than TerminateProcess().

    This will leave you immune to the vagaries of DLLs that don’t know how to shut down, and to the decisions of OS developers that change the workarounds for bad DLLs from release to release.

  15. Nick says:

    @Teo’s Vista bashing:

    I think you’re doing it wrong.

  16. Teo says:

    Because bashing Vista is always on-topic here, I’ll join :-)

    Things I adore in Vista:

    1. The Open/Save dialog that actually *shows* me where in the file system I am. Epic Win. Nothing else to be done in Vista, that would be enough to release it.

    2. The "Favourites" links at the top-left corner of Explorer, which are customisable with simple drag-drop. Epic Win.

    3. The per-application volume control. Epic Win.

    4. The new glossy shiny pretty icons

    5. The search in the start menu

    6. The search in control panel

    7. The iSCSI control UI

    8. The setupapi.dev.log – thank you, whoever designed and implemented it

    9. UAC – finally I could browse felling more secure

    10. The default sounds that were so good, that for the 1st time since Windows 3.0 era I kept them

    11. The ARP panel which doesn’t block while the uninstaller is running, taking  half the desktop real estate hostage

    12. IE7 which was tolerable, instead of extremely awful as IE6 was

    13. PowerShell. The CLI is unbearable, but the script language is awesome and it indeed has access to every corner of Windows so it is an epic win

    14. The new network redirector/server/cleint. yeah before SP1 it broke byte range locks, so that even Access was corrupting its DB files, but watching how files transfer in seconds instead of half an hour was incredible

    15. The new login screen, which was quite nice to the eye

    16. The boot speed

    17. the hybrid sleep, an epic win

    18. kernel mode transactions. they are a game changer

    19. the DWM which although all its inefficiencies (after all every software in its version 1 sucks) was an epic win both in usability and eye-candy

    20. the gorgerous new wallpapers

    21. the virtualization of registry/fs which fixed so many broken programs without messing with the OS

    22. the new component based OS module setup system, which means I do not need to search the damned disks when I want to install something

    23. the Windows Update UI which didn’t block the whole browser

    24. the fact that open/save dialogs are mini-explorers so you can do everything from there (including hosting broken shell extensions :-D)

    25. The new Task Scheduler, which

    25.1. has much better UI with richer functionality

    25.2. implements IDispatch so actually is usable by WSH

    26. The new interface and xml-based export/import functionality of Event Viewer

    27. The new Manage Computer MMC UI

    28. The responsiveness

    29. Superfetch

    30. The Windows Firewall UI

    31. The Volume Snapshot system which stopped sucking

    32. The System restore based on p30 above

    33. The WMI service which miraculously stopped corrupting its repository every 40 min

    34. The Performance Monitor

    35. The Task Manager

    36. Session 0 isolation

    37. Mandatory Access Controls ( can’t remember the official name right now, it’s well past midnight local time)

    38. The most used keyboard layout for my country, included by default for the very first time since Windows exists!

    39. The new fonts

    40. The heap manager, which for first time in Windows history doesn’t suck

    41. The virtually unlimited resources in kernel mode – the non-paged pool could be up to the whole physical memory minus handful of pages

    42. doesn’t suffer badly when a program opens more than 100 handles to kernel objects

    43. The WAIK that allows me to put any driver/program/setting into the setup media of Windows just like that

    44. The clock in the notification area

    45. The Bluetooth UI

    46. The Wi-Fi UI

    I guess you get the idea

    Things I truly hate in Vista:

    1. The Network Centre – it was a disaster, 3 years later I still cannot understand how to use it, I just blindly click on every link till I stumble on something that looks familiar enough – fixed in 7

    2. The loss of the drag-and-drop to a console app – fixed in 7.

    3. The broken nVidia drivers – you will not be surprised to learn that I blame MS for them, won’t you? I really find it an extra-human feat that such complex beasts can work with kernel interfaces designed in NT 3.1 era for then contemporary video cards. Oh, and the under-documented Windows kernel doesn’t help much.

    But all in all, it wasn’t a very satisfactory release – you definitely could put more bad things into it, so I have more things to complain about! Now just 3 – where is the fun in it?

  17. Mark says:

    Teo: you’re a hero.  Seriously, way to go, champ.

  18. Alexander Grigoriev says:

    @Teo,

    There are many good improvements in Vista and then in Win7. Some things are released undercooked, understandably. And there are things that were just broken. If people would not bitch about them, those things will remain broken forever. Take, for example, new help. It seems it’s using fulltext search instead of keywords. Thus, the results return so much noise, it becomes unuseable.

    Another example. Win7 and Vista SP1 got new exFAT filesystem optimized for USB flash and other removeable media. Unfortunately, it was not backported to XP. Thus, I and many others will be very reluctant to use it.

  19. slab says:

    @Alexander Grigoriev:

    There is an update you can install to get exFAT support on Windows XP, though: http://support.microsoft.com/?kbid=955704

    Unfortunately that requirement means that you still can’t just plug an exFAT volume into any XP computer without having first installed the patch, so there’s still reluctance.

  20. Gabe says:

    Alexandre Grigoriev: Just appending to a file isn’t going to work for log files with sessions, like setupapi.dev.log (#8 on Teo’s list of improvements). When I first implemented the setupapi.log in 1998, I was reluctant to group log statements by session because I thought that appending would be faster and more robust. However, as Teo makes clear, the current format is so much easier to use that it’s worth the overhead.

    So how do you implement per-sesson logging? You can either buffer all the messages and append them at once when the session ends, or do this for every message: lock the file; read it backwards until you find the beginning of your session; rewrite the sessions following yours; write out your session including the new log entry; and finally, unlock the file.

    Of course setupapi is doing driver installs that could crash the machine, so it has to log the slow way, but it should be clear that there is definitely merit to the first method.

  21. Alexander Grigoriev says:

    @slab:

    Thanks, that redeems MS sins! ;^)

  22. Alexander Grigoriev says:

    @Gabe,

    Re: Logging per session – Prefix each line with per-session unique ID (open time timestamp or like that), and per-session record number, and just append the lines for all sessions to the same file. Then, when you look at the file and want them grouped per session, either do grep, or simply sort the file.

  23. Yuhong Bao says:

    "Fortunately, this error doesn’t change the underlying analysis of How my lack of understanding of how processes exit on Windows XP forced a security patch to be recalled."

    Also, that security patch was released before Vista was released.

  24. DysgraphicProgrammer says:

    Now we just need a way to actually electrify the programmer who wrote the offending code. Not enough to kill (at first), just enough to hurt.  

Comments are closed.