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

问题描述

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

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

对于节点子进程,可以在Android Servicep.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的日志后为何不能杀死go服务器。

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

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