Looking at the world through kernel-colored glasses


During a discussion of the proper way of cancelling I/O, the question was raised as to whether it was safe to free the I/O buffer, close the event handle, and free the OVERLAPPED structure immediately after the call to CancelIo. The response from the kernel developer was telling.

That’s fine. We write back to the buffer under a try/except, so if the memory is freed, we’ll just ignore it. And we take a reference to the handle, so closing it does no harm.

These may be the right answers from a kernel-mode point of view (where the focus is on ensuring that consistency in kernel mode is not compromised), but they are horrible answers from an application point of view: Kernel mode will write back to the buffer and the OVERLAPPED when the I/O completes, thereby corrupting user-mode memory if user-mode had re-used the memory for some other purpose. And if the handle in the OVERLAPPED structure is closed, then user mode has lost its only way of determining when it’s safe to continue! You had to look beyond the literal answer to see what the consequences were for application correctness.

(You can also spot the kernel-mode point of view in the clause “if the memory is freed.” The developer is talking about freed from kernel mode’s point of view, meaning that it has been freed back to the operating system and is no longer committed in the process address space. But memory that is logically freed from the application’s point of view may not be freed back to the kernel. It’s usually just freed back into the heap’s free pool.)

The correct answer is that you have to wait for the I/O to complete before you free the buffer, close the event handle, or free the OVERLAPPED structure.

Don’t fall into this trap. The kernel developer was looking at the world through kernel-colored glasses. But you need to look at the situation from the perspective of your customers. When the kernel developer wrote “That’s fine”, he meant “That’s fine for me.” Sucks to be you, though.

It’s like programming an autopilot to land an airplane, but sending it through aerobatics that kill all the passengers. If you ask the autopilot team, they would say that they accomplished their mission: Technically, the autopilot did land the airplane.

Here’s another example of kernel-colored glasses. And another.

Epilogue: To be fair, after I pointed out the kernel-mode bias in the response, the kernel developer admitted, “You’re right, sorry. I was too focused on the kernel-mode perspective and wasn’t looking at the bigger picture.”

Comments (14)
  1. asdbsd says:

    Raymond, bullying kernel-mode developers since 1993.

  2. asdbsd says:

    Raymond, bullying kernel developers since 1993.

  3. Joshua says:

    As to whether or not that's fine, the kernel must protect itself from user mode corrupting it no matter what (documented or otherwise) the user mode process does.

    If a series of API calls crashes the kernel or wedges IO to the point where task manager cannot kill the process that's a kernel bug whether or not the caller's contract of the API calls was filled.

  4. John says:

    From a kernel developer perspective, applications only exist to provide test cases for the OS.

  5. David Walker says:

    Glad to hear that the kernel developer saw his mistake.

  6. NB says:

    The kernel wins as long as it does not crash, right?

  7. Joshua Ganes says:

    I love the autopilot landing analogy. It illustrates exactly how dangerous this one-minded thinking could be. I must admit to getting caught thinking this way in other situations from time to time.

  8. John says:

    It's better to kill everyone on the plane and land safely than to crash into a populated area.

  9. Alex Grigoriev says:

    @John:

    Linux overcommit behavior: "We've got too many passengers in the air and need to send more. Let's randomly shoot a plane".

  10. Alex Grigoriev says:

    Or another variant: "We're out of cargo containers. Let's shoot a plane and reuse some of its".

  11. NB says:

    Hm, I thought it was: "Let's eject some of the passengers".

  12. steveg says:

    SourceInfo si = krnlGetCallerSourceFile();

    if (si.QueryCheckInHistory("rchen").Count() > 0)

    {

       if (Rand(1000)==23)

       {

            krnlCrash("Take that, Raymond!");

       }

    }

  13. David Walker says:

    Don't mention "Rand", or you'll make me restate my favorite method of sorting an array:  Step 1: Permute the array randomly.  Step 2: Check to see if it's now sorted.  Step 3: If it's sorted, you're done; if not, repeat from step 1.

  14. Quantum Bogosort says:

    Eh, I never liked that implementation, it's got an O(n!) run-time. A better step 3 is: If it's sorted, you're done; if not, destroy the universe. Sure, you lose n! universes every time you sort, but there's an infinite amount of those. And it's O(n) in the survivors!

Comments are closed.