Open Eskibear opened 6 years ago
By changing the signal to "SIGTERM", it works in MacOSX, and moreover, the app shutdown more 'nicely'.
2018-08-02 13:02:09.175 INFO 36752 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 80 ms
2018-08-02 13:02:18.902 INFO 36752 --- [ Thread-3] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@25b485ba: startup date [Thu Aug 02 13:01:55 CST 2018]; root of context hierarchy
2018-08-02 13:02:18.904 INFO 36752 --- [ Thread-3] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
boot-dashboard-demo is inactive now.
Interesting. I beleave that from OS point of view 'SIGKILL' is a 'stronger' signal than 'SIGTERM'.
Although SIGKILL is defined in the same signal header file as SIGTERM, it cannot be ignored by the process. In fact, the process isn't even made aware of the SIGKILL signal since the signal goes straight to the kernel
Quoted from: https://major.io/2010/03/18/sigterm-vs-sigkill/
So I assume this is a OS X specific thing. Perhaps OS X doesn't allow process to use SIGKILL on other processes.
I also wonder how this translates to Windows environment?
BTW: From my experience implementing process termination can be quite complex. There are a number of mechanisms that can be used.
1) using JMX to ask a boot app to terminate 2) sending OS level signals of different strength (like SIGKILL, SIGTERM)
This can become complex because
a) The JMX mechanism is the only one that really works independent of OS but
b) OS signals don't work exactly the same on all OS's.
Generally, what we have implemented is to start by using JMX to 'ask nicely' and after some timeout become more aggressive at terminating process more directly.
See: https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html
We use the destroy()
and destroyForcibly()
methods which I assumed correspond to SIGTERM and SIGKILL on linux systems and might be something different on other OS but implementing the same 'intent'.
So I assume this is a OS X specific thing. Perhaps OS X doesn't allow process to use SIGKILL on other processes.
I was talking about "SIGINT" instead of "SIGKILL". SIGKILL is the "strongest" signal as far as I know. SIGTERM is the default signal for the command kill
in MacOSX. Both can terminate the process.
Following is a list of signals defined in MacOSX. (And I think it's compatible with x86 Linux)
No Name Default Action Description
1 SIGHUP terminate process terminal line hangup
* 2 SIGINT terminate process interrupt program
3 SIGQUIT create core image quit program
4 SIGILL create core image illegal instruction
5 SIGTRAP create core image trace trap
6 SIGABRT create core image abort program (formerly SIGIOT)
7 SIGEMT create core image emulate instruction executed
8 SIGFPE create core image floating-point exception
* 9 SIGKILL terminate process kill program
10 SIGBUS create core image bus error
11 SIGSEGV create core image segmentation violation
12 SIGSYS create core image non-existent system call invoked
13 SIGPIPE terminate process write on a pipe with no reader
14 SIGALRM terminate process real-time timer expired
* 15 SIGTERM terminate process software termination signal
16 SIGURG discard signal urgent condition present on socket
17 SIGSTOP stop process stop (cannot be caught or ignored)
18 SIGTSTP stop process stop signal generated from keyboard
19 SIGCONT discard signal continue after stop
20 SIGCHLD discard signal child status has changed
21 SIGTTIN stop process background read attempted from control terminal
22 SIGTTOU stop process background write attempted to control terminal
23 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2))
24 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2))
25 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2))
26 SIGVTALRM terminate process virtual time alarm (see setitimer(2))
27 SIGPROF terminate process profiling timer alarm (see setitimer(2))
28 SIGWINCH discard signal Window size change
29 SIGINFO discard signal status request from keyboard
30 SIGUSR1 terminate process User defined signal 1
31 SIGUSR2 terminate process User defined signal 2
I also wonder how this translates to Windows environment?
"Windows does not support sending signals, but Node.js offers some emulation with process.kill(), and subprocess.kill(). Sending signal 0 can be used to test for the existence of a process. Sending SIGINT, SIGTERM, and SIGKILL cause the unconditional termination of the target process." Ref: https://nodejs.org/api/process.html#process_signal_events
And that is exactly the reason for the "known issue" in PR https://github.com/Microsoft/vscode-spring-boot-dashboard/pull/18 In windows, it simply "causes the unconditional termination".
Thanks for the extra information. I see somehow I confused SIGKILL and SIGINT. But yes, I think SIGTERM and SIGKILL are the signals we should be using on Linux and OS X. I suggest a strategy that sends increasingly stronger signals, trying to be nice first and then becoming increasingly aggressive if the nice way fails. So in this order JMX -> SIGTERM -> SIGKILL.
BTW: SIGTERM and the JMX approach are similar in that they are a 'nice request' sent to the process. This means that not every process is guaranteed to obey it. Buggy or stuck apps can disobey SIGTERM (an example might be a buggy shutdownhook in the process that deadlocks). So its a good idea to keep using SIGKILL as fallback when a process doesn't terminate within some reasonable time after receiving SIGTERM.
Agree with using JMX -> SIGTERM -> SIGKILL eventually to get better experience. For the first step, let me change SIGINT to SIGTERM to unblock MacOSX.
Code here: https://github.com/Microsoft/vscode-spring-boot-dashboard/blob/master/src/Controller.ts#L57-L65
In MacOSX, after clicking "Stop", sending "SIGINT" to kill, the value of
app.process.killed
istrue
, but actually the process is not terminated.