The dangers of destroying a window while it is processing a sent message


Commenter BryanK wonders why weird things happen if you destroy a window while it is processing the WM_ACTIVATEAPP message. He suspects that it’s similar to the problems you encounter when you destroy a window in response to the WM_KILLFOCUS message.

Although I haven’t studied the WM_ACTIVATEAPP situation, I wouldn’t be surprised if the problem is indeed entirely analogous. It just follows from general programming principles: After all, you are destroying the active window. The WM_ACTIVATEAPP message is sent as part of the activation change, and the documentation says that the message is sent “when a window belonging to a different application than the active window is about to be activated.” Notice: “about to be” activated. That other window hasn’t been activated yet; you’re still the active window.

Destroying the active window means that the window manager has to find a new active window. You’re triggering an activation change while another activation change is in progress; no wonder things get all messed up.

I am now going to make a gross generalization. There may be exceptions to this rule, but it’s a good place to start: Destroying yourself is (generally speaking) not an acceptable response to a sent message. The code that sent you the message is doing so because it wants to ask you a question (if it cares about the return value) or because it’s informing you of something that is happening right now as part of a larger operation. (After all, if the code didn’t mind if you received the information after the fact, it would have posted the message instead of sent it.)

And (generally speaking) it’s bad form to perform an operation that changes a system’s state while it’s notifying you that that very state change is in progress. When the state change is in progress, the state is unstable. (If it were stable, then the state change would either not yet have begun or already have finished!)

Comments (14)
  1. fluidphreak says:

    So, post yourself a custom message if you need to destroy yourself in response to a sent message…

  2. S says:

    So, post yourself a custom message if you need to destroy yourself in response to a sent message…

    If you’re a top level window, it needn’t be all that custom – WM_CLOSE does the trick. In fact, I can’t think of a good reason not to do that for child windows either.

  3. Alexandre Grigoriev says:

    Normally, the top-level window should only be destroyed when called from the top-level message loop; not from any other modal loop. Otherwise, if you already destroyed your objects, you could touch them on the way up from the modal loops, and that would crash the app.

  4. Koro says:

    That reminds me of a similar hard to track bug I had with the tooltip control.

    I was using a balloon tip and inside some notification, I ordered to control to destroy itself. As soon as I returned from the notification, it would crash.

    Turns out it was accessing some member in its data structures on return, which it just destroyed "from within" the callback because of my code.

    Still, it took me a while to find it, since I didn’t know where to look for. Solved it by posting the "destroy yourself" message from the callback instead.

  5. fred says:

    Not a good generalization really.

  6. Goplat says:

    WM_CLOSE itself seems to be a sent message; it doesn’t go through the message pump (when it occurs as a result of clicking the X, at least). Is WM_CLOSE an exception to the rule?

  7. Yuhong Bao says:

    Reminds me of when I experimented with doing a longjmp up to the message loop in response to a sent message. Vista and later wrap what is effectively a SEH block around all user-mode callbacks, so that if the longjmp is exception-safe and thus uses RtlUnwind to unwind the stack, the exception handler will automatically return from the callback.

  8. jon says:

    @Goplat: If the rule in question is "Don’t destroy yourself when something sends you a message if the sender isn’t expecting it", then clearly WM_CLOSE is ok – because the sender IS expecting you to destroy yourself.

  9. q says:

    This message will destroy itself in 10 seconds.

  10. Bill says:

    I seem to recall a Win32 API named PostQuitMessage(exitCode) located in user32.dll. This would be the correct way to destroy (quit, close, etc) your entire application, no? Just closing a window, I would think PostMessage WM_CLOSE is the way to go. Which I think is what has already been said.

  11. S says:

    If you post it to yourself WM_CLOSE is definitely a posted message. You don’t *have* to do the same as the system does in all cases. If you’re in a context where destroying you’re window would be bad, post yourself a WM_CLOSE message – you don’t even need to handle it, as DefWindowProc will do the right thing and destroy the window.

    If the system sends you WM_CLOSE in response to clicking on the close button, it is probably doing it because it is already in the context of a posted message handler (WM_NCLBUTTONUP is a posted input message) and it is probably coded to handle the window destroying itself – it had better be since this is what DefWindowProc will do.

  12. S says:

    "I seem to recall a Win32 API named PostQuitMessage(exitCode) located in user32.dll. This would be the correct way to destroy (quit, close, etc) your entire application, no? Just closing a window, I would think PostMessage WM_CLOSE is the way to go. Which I think is what has already been said. "

    No – PostQuitMessage doesn’t do that – PostQuitMessage sets a flag on the message queue which indicates that GetMessage should return FALSE. This may cause the thread to exit, destroying the windows as it goes, but it might not. The way I’ve always done it is to post WM_CLOSE, have DefWindowProc call DestroyWindow in response to WM_CLOSE, then call PostQuitMessage in my WM_DESTROY handler (assuming this is the applications main window).

  13. waleri says:

    >> When the state change is in progress, the state is unstable.

    True, but what does the message tell us? That state is changing or that state is already changed. In some cases it is clear, like in WM_SIZE/WM_SIZING, but in others it is a guess. I do believe though that messages usually report state changed, not changing in progress.

    Usually the bigger problem is passing message for further handling, after the window is already destroyed.

  14. Kevin says:

    I just want to notify a window that I think it should kill itself, like, right now. Whether or not the window’s self esteem is high enough to keep itself alive is not really my problem.

Comments are closed.