Execute Code on task kill

Hi everyone,

i'm currently working on a sockets project, and i want to recognize wheather the clients process is killed, but this is not windows topic. My question is if theres any option to execute code when f.ex the task is beein killed, so that i can send a last message to the server bevore the tasks gone.

Thanks in advance,

Luke
Last edited on
When a process is "killed", e.g. via signal SIGKILL on Unix/Linux or via TerminateProcess() on Windows, the process dies immediately and there is no way for that process to do anything about it!

From the server's perspective, the socket connection is closed. I don't think there is a way to tell whether the process "actively" closed the connection, or the connection was closed because the process has been terminated. Of course, the server and the client could agree to exchange a certain "goodbye" message before a graceful shutdown. If the connection is closed without receiving that message first, then the server knows that the client did not shut down cleanly. Maybe it crashed, maybe it was killed, maybe the network broke...

_________

Unlike the SIGKILL signal, the SIGTERM signal can be caught and handled by the application. Similarly, on the Windows platform, when a GUI application receives a WM_CLOSE message, it can react to that message. In both cases, the application is supposed to quit ASAP, but can do some "clean up" work before terminating.

The crux is: You don't know how your application is going to be terminated. Also, at any time, the network can break. You just can not be certain that you'll get the chance to do some final "clean-up" work...
Last edited on
Ok, thank you. but can i then prevent a user from killing the process manually, so that it cannot be killed via taskmgr, such as intercept TerminateProcess(), if not how can it be possible that theres f.ex malware out there, which cannot be closed that easy?
Last edited on
not always, no.
If the operating system issues a "YOU DIE NOW" type interruption and killed the process, you can't do anything about that (?) or at least not easily.

If you got a user close of the program, or the os sends that lesser command (eg shutting down, program# 42 please exit normally now) on the user's behalf, you can.

in windows you would catch a message (on exit or some such) and put your final send in the handler. I do not know what other OS need there, but it could vary from simply doing it before the end of main to needing a similar event handler message.

another technique is to have a watchdog program. One of our critical embedded systems worked that way, program A started when the system booted, and all program A does is scan the list of tasks from the OS and if program B is not listed, (and in our case, programs C, D, ... about 10 of them) it starts that program. In your case, instead of starting the program that failed/died you would send a network package, though ... but in your case, program A would start after B, so you don't spam the package before anything even gets started. Convoluted... B starts A, and A sends a package if B is not running. This counters the OS instant kill command, as long as it did not also kill the other program. The programs can mutually start each other if not running -- some virus work this way, its a bit harsh but necessary on some systems -- to ensure that they are always up.

some malware claims to be protected OS level process. On windows, you can somehow designate programs to not be killable: most virus programs and some critical OS services won't let you kill them. I don't know if that is possible on unix if you have full admin rights. And again, some of the malware has multiple programs that all start each other.
Last edited on
Ok, thank you. but can i then prevent a user from killing the process manually, so that it cannot be killed via taskmgr, such as intercept TerminateProcess(), if not how can it be possible that theres f.ex malware out there, which cannot be closed that easy?

No, not with "normal" methods. Maybe with "rootkit" (malware) techniques that hook system calls ;-)

Normally, if process #A has the required privilege to kill process #B, and process #A calls TerminateProcess() on process #B (or sends signal SIGKILL), then process #B has no chance to react. It just dies immediately.

Only if process #B was started by a "superuser" (or is a fundamental system process) whereas process #A is running in the context of an "unprivileged" user, then process #A is not allowed to kill process #B.

Also, keep in mind that "killing" a process by the user is only one way for the process to die "unexpectedly". The process could also crash for whatever reason. Or the network connection could break away...

You just can not expect the process to be able to send a final message in any possible case!

in windows you would catch a message (on exit or some such) and put your final send in the handler. I do not know what other OS need there, but it could vary from simply doing it before the end of main to needing a similar event handler message.

But only if someone is trying to "gracefully" shut down your application, e.g. by sending a WM_CLOSE message to its top-level window. If, instead, your process is terminated the "hard" way, e.g. via TerminateProcess(), then you don't get any notification message beforehand; also no atexit() handlers will be executed.
Last edited on
OK, thank you very much
We can have a monitor process that waits on the process of interest with
WaitForSingleObject( process_handle, INFINITE ).
The process object would be signalled even if the process is killed.

Things get more interesting if we have to also take care of the monitor process itself getting killed or crashing.
that is why I said a separate program; in case the thread tree is killed with the parent. Even that only gets you so far, if everything is being killed. The last step you might take at that point is to have the os spawner kick one off every little bit, windows task scheduler tool or cron on unix can do that.
Well, you can have a separate "monitor" process that waits for the "main" process to terminate. But the "monitor" process still would not be able to send a message back to the server over the same socket connection that existed in the now-deceased "main" process; the connection is closed as soon as the "main" process dies. So, the "monitor" process would have to create a new/separate connection in order to signal to the server that the "main" process has died. But that's probably not what the OP had in mind.

And all this won't help if the network breaks, or if the whole system has a power outage or BSOD ;-)

I think there will always be cases where the connection to the client is closed unexpectedly, i.e. without a "clean" shutdown sequence. And, therefore, the server needs to be prepared to handle this case...
Last edited on
WSADuplicateSocketW()
...
The WSADuplicateSocket function is used to enable socket sharing between processes. A source process calls WSADuplicateSocket to obtain a special WSAPROTOCOL_INFO structure. It uses some interprocess communications (IPC) mechanism to pass the contents of this structure to a target process, which in turn uses it in a call to WSASocket to obtain a descriptor for the duplicated socket.
...
Shared sockets are typically used to having one process that is responsible for creating sockets and establishing connections, and other processes that are responsible for information exchange.
...
The underlying socket, however, will remain open until closesocket is called by the last remaining descriptor.
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaduplicatesocketw
That is good to know, thanks JL. I have never needed to do that, and had no idea this existed!
Topic archived. No new replies allowed.