如何销毁 Android 上的 golang 子进程?

How to destroy a golang sub process on Android?

最近,我正在尝试使用 Runtime.getRuntime().exec(command) 的 Android 子进程,发现我可以破坏 NodeJS http 服务器但不能破坏 Go http 服务器。

对于 nodego 二进制文件,可以从 Termux 获得;

对于节点子进程,可以在AndroidServicep.waitFor()中启动;到时候可以被p.destroy()

杀死

但是,对于go子进程,它可以启动但不能被p.destroy()甚至p. destroyForcibly()杀死;在这篇文章 https://medium.com/honestbee-tw-engineer/gracefully-shutdown-in-go-http-server-5f5e6b83da5a 中,它确保可以正常关闭 go 服务器,我试过了,但 p.destroy() 仍然不起作用。

如果有人能告诉我一个终止进程的方法,我将不胜感激。谢谢!

刚刚想出了一个破解方法;不优雅;指导我找到更好的解决方案!

Log.d("AppDebug", p.javaClass.getName())
// from above log
// we can know Android use "java.lang.UNIXProcess" as implementation of java.lang.Process

// to make sure the sub process is killed eventually
if (p.isAlive()) {
    val klass = p.javaClass
    if (klass.getName().equals("java.lang.UNIXProcess")) {
        Log.d("AppDebug", "force terminate sub process ..")
        try {
            val f = klass.getDeclaredField("pid");
            f.setAccessible(true);
            val pid = f.getInt(p);
            // XXX: buggy here, if getInt throw an error, the filed is exposed!
            f.setAccessible(false);
            android.os.Process.killProcess(pid);
            Log.d("AppDebug", "force terminating done.")
        } catch (e: Exception) {
            Log.d("AppDebug", "force terminating failed.")
        }
    } else {
        Log.d("AppDebug", "force terminating not supported.")
    }
}

对不起我的误导。目前我完全理解为什么我添加了一些关于 ps -ef before/after 终止进程的日志后无法终止我的 go 服务器。

实际上我使用go run main.go来启动服务器;但是,go run main.go 将编译代码并在 tmp 文件夹中生成一个二进制文件;然后它将产生一个子进程(执行二进制文件);当我执行 p.destroy() 时,它只是终止了 go 进程,但子服务器进程仍然存在。

正确的解决方案是,像上面的代码一样得到pid;并使用 ps -o pid= --ppid=<pid> 获取子树并终止所有进程进行清理。