Sunday, March 27, 2011

[C#] Deallocate resources on process termination

Hi all,

I'm sorry for the trivial question. How I can deallocate resources when the process gets killed by, for example, the Task Manager? Is there a way to call a function before the process gets closed?

Thanks in advance


Thanks to all for your answers. I think I will implement a watchdog process as suggested.

From stackoverflow
  • Theoretically the O/S should deallocate resources after the process is killed. What kind of resource are you thinking of in particular?


    Edit:

    Ok, it's kinda tricky to explain. I'm using a library that is wrapping some OS functions to manage some Shell Extensions. When the application closes without calling explicitly the appropriate methods, all explorer freezes and I need to restart it.

    Any unmanaged DLL is (according to the documentation) supposed to be invoked with a DLL_PROCESS_DETACH event; however, this DLL_PROCESS_DETACH event isn't called when the process is terminated via the TerminateProcess API.

    Googling for these terms turned up The Old New Thing : Why can't you trap TerminateProcess? which says, "Once you kill with TerminateProcess, no more user-mode code will run in that process. It's gone."

    Because everything you're trying to work with (i.e. .NET, Explorer, Shell, COM) is happening in user-mode, I think the answer is that there's no way to do what you want.

    Instead, perhaps there's another way: for example, by adding code to your Shell extensions so that they realize if your process is abended.

    : Ok, it's kinda tricky to explain. I'm using a library that is wrapping some OS functions to manage some Shell Extensions. When the application closes without calling explicitly the appropriate methods, all explorer freezes and I need to restart it.
    Barry Kelly : DLL_PROCESS_DETACH is not passed to DllMain when the termination is caused by TerminateProcess.
    ChrisW : Thanks Barry: I'll edit my answer accordingly.
  • You could try wrapping your whole process in a try/finally statement (you put the deallocation stuff in the finally clause), but in some cases even that will not be enough.

    Actually, I think you could launch a background thread from your process to do all the stuff and Thread.Join() with your main thread so that if something goes wrong in the child thread, the main thread will be still able to get things right. Of course, this will not work if the whole process gets terminated for some reason.

    You could also launch a child process and call Process.WaitForExit() but I'm not sure if your shell-related thing could work with a multi-process approach.

  • Take a look at Critical Finalizers:

    http://msdn.microsoft.com/en-us/magazine/cc163716.aspx

    Barry Kelly : Critical finalizers can do nothing in the case of a call to TerminateProcess, such as by Task manager.
    Ray Booysen : As Barry said, these won't ever execute.
  • Hi Bardakargor,

    There really is nothing you can do if your process is killed. By definition, killing a process is just that - killing it. The process does not get an opportunity to run any code. This is very much "by design".

    Imagine that you could register a routine that was called when your process was killed by the user (or by another process). What would it do? All the other threads in your process would be in an indeterminate state, How would you synchronize with them? Remember, the idea is that the process needs to be killed.

    The other scenario is even tougher: your code is benign and trying to do the right thing - e.g. clean up and be a good system citizen. Some code isn't. Imagine what a boon to a malware author it would be if the OS allowed code to be run for a process that was being killed. It would be bad enough for malicious processes that were running with standard user privileges, and completely awful for any running with administrative privileges.

    Critical finalizes and structured exception handling will not solve this fundamental issue.

    ON the upside, the OS will free all the resources it knows about when your process is killed, namely memory and kernel objects. Those will not leak. But explorer doesn't know about your process so it cannot clean up for it.

    One way to solve this would be to have a monitoring process that keeps track of your other processes state and cleans up for it. You could do this with a simple process, or with a service. You might also consider some kind of shell extension that had its own thread that did the same thing.

    Best Regards RGR

    : Thanks Foredecker for your detailed answer. I appreciated it.
  • There is no way to execute arbitrary code upon termination within a process which is about to be killed by a call to TerminateProcess, such as by Task Manager, or another process utility such as TSKILL or TASKKILL.

    Neither critical finalizers, nor ordinary finalizers, nor try/finally blocks, and certainly not mere objects which implement IDisposable can cause code to be executed in this scenario. Even DLL detach events will not be invoked from a process termination via TerminateProcess.

    The best you can do is to use a watchdog process which monitors your original process and executes relevant code when the original process is terminated.

0 comments:

Post a Comment