Unity3D’s portable runtime based on Mono has become a great “write once run everywhere” tool for interactive apps or video games. However stable it is, there is always some edge cases to portability. The handling of SIGTERM, SIGINT, etc… linux (well, POSIX) signals are one of them.
The bug
Make a dummy unity3D app. Make it do some work in OnApplicationQuit()
callback. Get it’s PID and terminate it with kill <pid>
. The exit handler never get called.
Other app lifecycle events like GameObject.OnDestroy()
obviously won’t get called either because scene cleanup is a consequence of a proper exit sequence.
linux(UNIX/POSIX/whatever) exit signals behaviour is well documented. Generally only two of them will ask for specific exit handlers :
Common name | N° | Action |
SIGINT | 2 | Interruption |
SIGTERM | 5 | Exit request |
Lots of ways exists to handle signals under Mono. However Unity3D really is a thing of its own. As such, it doesn’t let us catch those little things.
The fix
As a “temporary” fix, I made a barebones C file to catch the process’s signal :
sighandler.c
It compiles easily to a “.so” shared library
gcc -shared -o libsighandler.so -fPIC sighandler.c
The output file (compiled on debian jessie) can be downloaded here.
We need this file in Assets/Plugins
to be automagically exported on build targetting linux platform. Then it needs to be referenced from Unity Scripts. In C# :
Note: print()
statements get logged to ~/.config/unity3d/<company_name>/<app_name>/Player.log
.
This will override system’s default SIGTERM and SIGINT handlers and let you act accordingly. Note that it’s bad behaviour to take more than a few seconds to exit. As such, most window managers will SIGKILL the process after a few seconds. SIGKILL by itself is interruptible so behave!