What happens to a named object when all handles to it are closed?


A customer had a question about named kernel objects:

I understand that handles in a process if leaked will be destroyed by the kernel when the process exits. My question would be around named objects.

Would named objects hold their value indefinitely? If I run a small utility app to increment a named counting semaphore, the count of that named semaphore could be lost when that app exits?

I would expect it to always hold its current value so that transactions across processes and across time could be held even if no process is holding on to it.

When the last handle to a named kernel object (such as a named semaphore or a named shared memory block) is closed, the object itself is destroyed. Doesn't matter whether you explicitly closed the handle by calling CloseHandle or the kernel closed the handle for you when it cleaned up the mess you left behind. The object manager doesn't say, "Well, if the application explicitly called CloseHandle, then I'll also delete the named object, but if the application leaked the handle, then I'll leave the named object around."

First of all, that would kind of belie the whole concept of clean-up. Cleaning up means destroying the resources the application neglected to.

Second, this would create a bizarre situation where the way to access a new feature is to intentionally do something wrong. (Namely, to leak a handle to a named object.)

Okay, so maybe the expectation was that named objects persisted after all handles to them are closed, even if the handle is closed via the normal CloseHandle mechanism. But then how would you delete a named object? There is no DeleteNamedEvent function, after all. You could write a process that created 2 billion named objects and then leaked them. Boom, now you can't clean up by killing the process; you have to restart the computer.

Kernel objects all follow the same lifetime rules, whether they are named or anonymous: The object is destroyed when the last reference to it is removed (when the handle is closed, noting also that running threads and processes keep a reference to the corresponding kernel object).

If you want something that survives after all its handles are closed, then use something with a persistence model, like a file.

Comments (14)
  1. Or the registry.  Or write a service.

  2. Wizou says:

    Or maybe use DuplicateHandle to keep a reference to the object in your other processes?

  3. Andreas Rejbrand says:

    Isn't this at the very heart of a modern operating system, not to let a single process damage the system?

  4. gigi says:

    Linux does persist various objects after a process exits, like memory maps or semaphores. This can be a major pain in the ass, since you need to make sure the object does not exist anymore when starting your process again if you want to start from a clean object.

  5. Asa says:

    I know that in kernel mode, kernel objects can be either permanent or temporary. The decision for such is made at device creation time, but a permanent device can be made temporary to remove it. ZwMakeTemporaryObject ( msdn.microsoft.com/…/ff566477(v=VS.85).aspx ) would be the kernel mode method of doing that.

    To make it stick around though you have to set OBJ_PERMANENT when performing InitializeObjectAttributes. The flag is described as "This flag only applies to objects that are named within the object manager. By default, such objects are deleted when all open handles to them are closed." ( msdn.microsoft.com/…/ff547804(v=VS.85).aspx )

  6. Archer says:

    I am sorry but I was a little confused…Do you mean that a named kernel object would be deleted even the process who had created it exits without calling the CloseHandle? Thanks for an advanced explanation~

  7. Paul Rose says:

    In linux/unix typically named objects are treated like files in that they exist until deleted.   Sometimes this is extremely handy, like when you want persistence but a file doesn't exactly fit the bill.   The issue of having the objects pile up and having to restart the system is really no different than if a Windows app were to create billions of files and not delete them.  In linux you can delete the named object just like you can delete a file.

    The Windows and unix ways are simply different, and there are advantages and downsides to both.  When writing a native application for either, I rarely have trouble.   When trying to port an application that uses named objects from one to the other, it can be a pain.

  8. 640k says:

    A good OS should close handles to all objects when a process crash. Sloppy OS don't.

  9. Alex Grigoriev says:

    @Archer:

    Let me repeat that for you:

    "When the last handle to a named kernel object (such as a named semaphore or a named shared memory block) is closed, the object itself is destroyed. Doesn't matter whether you explicitly closed the handle by calling CloseHandle or the kernel closed the handle for you when it cleaned up the mess you left behind."

  10. Gabest says:

    Not just closed, but also released (mutex). It wasn't so obvious to me at first.

    [Um, if the object is destroyed, it doesn't have a released/not released state. (Or are you talking not about object destruction but merely handle closure at process termination? [I.e., are you changing the subject?] In which case the behavior you describe is a specific behavior for mutexes, not a general property of kernel objects.) -Raymond]
  11. Gabe says:

    Paul Rose: What objects in Linux are named but not files? I know there are named pipes, devices, and directories, but those aren't shared memory or semaphore. Perhaps you're talking about SYSV IPC primitives (shared memory, semaphores)? They stick around until explicitly deleted (or the system reboots), but they're not named.

  12. Paul Rose says:

    Gabe: we use shm_open with names in /dev/shm.   We take advantage of the persistence to save time on process restarts, but we can always delete via rm if things go wrong.  

    On windows builds we use CreateFileMapping and do without the persistence.

    The linux app typically restarts much faster, but once in a blue moon requires that we manually clean up.   The winodws app restarts slower but is a little more bulletproof.

    Again, no different than a file.

  13. Nitpick: your inline response to Gabest has the following mismatched parenthetical structure: {([])]

    [I was hoping not to have to go back and re-edit for punctuation. I guess everything has to be perfect around here. -Raymond]
  14. MikeCaron says:

    [I was hoping not to have to go back and re-edit for punctuation. I guess everything has to be perfect around here. -Raymond]

    You should have added #pragma nipick(disable:4699)

    On topic, this is one of those blog entries that make me — involuntarily, mind you — go "Duh!" Outstanding handles are closed when the process dies, and objects are destroyed when there aren't any more handles. Any further explanation is just fluff.

    (note, this is not a criticism of your writing, but a criticism of someone who is unable or unwilling to think things through to their logical conclusion)

Comments are closed.

Skip to main content