Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get process PID, use it to send SIGTERM #120

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mrdziuban
Copy link

Fixes #20

Updates AppProcess to hold onto a ProcessWithPid, which is a new type defined in the scala.sys.process package. Given a standard Process, the ProcessWithPid.apply method will do its best to get the PID of the Process.

Unfortunately the only way to do so is via reflection. We first have to reflect on the private scala.sys.Process.SimpleProcess#p field to get the underlying java.lang.Process. We then try to call the java.lang.Process#pid() method, which exists in Java 9 and above. If that fails with a NoSuchMethodException, then we fall back to looking at the private java.lang.ProcessImpl#pid field, which works in Java 8 and below.

When a PID is discovered, AppProcess uses it to send a kill -15 <pid> to the process. It will wait 10 seconds for the process to exit before forcibly killing it with process.destroy().

When we fail to discover a PID for any reason, AppProcess will just forcibly kill the process with process.destroy(), as it currently does.

@@ -0,0 +1,48 @@
package scala.sys.process
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be in the scala.sys.process package so it has access to Process.SimpleProcess, which is package private

Comment on lines +20 to +24
val method = classOf[JProcess].getMethod("pid")
method.invoke(p) match {
case pid: java.lang.Long => pid
case pid => throw new RuntimeException(s"Expected process PID ($pid) to be a Long, but it was a ${pid.getClass.getName}")
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're content with requiring everyone who develops sbt-revolver to use Java 9+ to do so, then this could be simplified to just p.pid, plus changing the catch block to handle NoSuchMethodError when users are on Java 8.

Otherwise, compiling this on Java 8 fails with an error

/Users/matt/sbt-revolver/src/main/scala/scala/sys/process/ProcessWithPid.scala:21:9: value pid is not a member of Process
      p.pid
        ^


private def killProcess(pid: Long): Unit = {
val exited = try {
JRuntime.getRuntime.exec(s"kill -15 $pid").waitFor(10, TimeUnit.SECONDS)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to suggestions on how long this waits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Shutdown Hooks Not Running
1 participant