为什么不抓住来自Java进程的信号.destroy()

时间:2018-03-27 21:12:44

标签: java linux bash process kill

测试脚本

下面的脚本会挂起,直到您按 Ctrl + C ,然后关闭需要两秒钟。我写这篇文章是为了调查Java的process.destroy()

#! /usr/bin/env bash
# dieslowly.sh
bail() {
    echo exiting...
    sleep 2
    echo ...exited

    trap - SIGINT SIGTERM
    kill -- -$$
}

trap bail SIGTERM SIGINT

echo "running..."
sleep infinity

我认为它有效,因为:

  • 如果我运行./dieSlowly.sh并按 Ctrl + C ,则会等待两秒钟然后退出
  • 如果运行./dieSlowly.sh,然后在另一个终端运行kill -2 -<pid>,则等待两秒钟然后退出

流程处理测试

此(Java)测试调用bash脚本,并尝试允许它慢慢关闭

void kill_dummy()
{
    // Run the test script
    Process process = new ProcessBuilder("./dieSlowly.sh").start();

    // terminate the process, wait for it to stop, then kill it
    DateTime before = new DateTime();

    process.destroy(); // this doesn't seem to do anything

    // Runtime rt = Runtime.getRuntime();
    // rt.exec('kill -9 ' + process.pid);  // this kills it too fast
    // rt.exec('kill -2 -' + process.pid); // this doesn't kill it at all
    // rt.exec('kill -2 ' + process.pid);  // neither does this

    process.waitFor(4, TimeUnit.SECONDS);
    process.destroyForcibly();
    DateTime after = new DateTime();

    // expect it to have taken less than four secongs 
    assert (after.getMillis() - before.getMillis() < 4000);
}

我希望测试大约需要两秒钟 - 这是脚本自行关闭所需的时间。

相反,它需要大约四秒钟。使用调试器我已验证destroy()调用无效。这会导致waitFor超时。 destroyForcibly()然后以极端的偏见杀死这个过程 - 我想避免这种过程。

进程树

如果我在destroyForcibly()上放置断点,则ps axjf命令会显示此树:

\_ -zsh
|   \_ /bin/sh /opt/idea-IC-172.4343.14/bin/idea.sh /path/to/my/project
|       \_ idea
|           \_ idea
|               \_ bash ./dieSlowly.sh
|                   \_ sleep infinity
\_ -zsh
|   \_ -zsh
|   \_ bash ./dieSlowly.sh
|       \_ sleep infinity

我的问题

我可以进行哪些修改,以便测试在测试中触发慢速关闭路径?

修改

我知道信号是特定于操作系统的东西,而JVM因其打算独立于操作系统而受到限制。但是,当我从JVM运行kill -9 <pid>时,我成功地终止了进程,所以似乎可以将命令中继到操作系统并让它发送信号。

假设我无法使用process.destroy(),那么问题就变成了:

  

为什么我可以从JVM调用kill -9,而不是kill -2

0 个答案:

没有答案