Is there a way to prevent SIGKILL after SIGTERM for a daemon\agent during shutdown\restart?
i have a daemon that must be finished gracefully. It should have CUSTOM amount of time before system sends SIGKILL and kills it.
Is there a possibility to do such thing on MAC?
Yes, this is definitely possible.
If you start your service properly via launchd, you can define the amount of time you need for stopping the service with the "ExitTimeOut" key in the launchd plist for your service. If you set "ExitTimeOut" to for example 300, this means your service have 300 seconds (5 minutes) to do something in between receiving SIGTERM and actually being killed by receiving the SIGKILL signal.
Another possibility is to redefine the shutdown sequence as such. This is a more "hacky" solution, but if this is intended only for your own Mac, it could be the easiest.
A way to do this is simply to replace /sbin/shutdown with a program of your own liking. An idea is to move the original /sbin/shutdown program to for example /sbin/shutdown.apple and then add a simple shell-script in its place.
The shell script should look something like this:
#!/bin/bash
notify_my_program
sleep 300
exec /sbin/shutdown.apple "$@"
The "notify_my_program" should be replaced with something that tells your service to shutdown. It could be as simple as sending it the SIGTERM signal.
Please ensure that you have the proper permissions on the shell script (i.e. the same as the original shutdown program).
After the above mentioned modification, your system should at shutdown first notify your service to shutdown, wait 5 minutes and then do whatever it usually does at shutdown.
The modified shutdown process should be used when you shutdown from the command line as well as when doing it from the GUI (i.e. from the Apple menu).
Finally, a more involved solution would be to actually replace launchd with your own custom init system. The simplest way to do that would be to download the source code for launchd, change the shutdown sequence, recompile and replace launchd on your system. The /sbin/shutdown program works just by sending a signal to launchd (various signals for reboot, halt, poweroff, etc.) - so the actual shutdown sequence for the user-space part of the system is actually handled by launchd, so in this manner, you can customize it to do anything you want.
Note that changing the shutdown sequence in either of the two mentioned ways require you to disable SIP (System Integrity Protection) before proceeding.
No - this isn't the decision idiom on macOS so your development requirements are conflicting with the system design intention.
Your daemon should be dealing with this and timing and technical ways to do this are built in to MacOS as well as documented fairly well by Apple.
macOS does not shutdown daemons by just sending a SIGKILL it first sends a SIGTERM and then only if the process is still there a SIGKILL. You have some control to delay this by using the disableSuddenTermination method on NSProcessInfo see https://developer.apple.com/documentation/foundation/nsprocessinfo/1412841-disablesuddentermination?language=objc
Thus your daemon should be shutting down on receipt of a SIGTERM and so the SIGKILL will have no effect.
This was documented in Apple's The Life Cycle of a Daemon
It is also the normal BSD and Linux way of shutdown except that launchd is not involved.