mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 10:45:23 +08:00
Change session exit detection
Previously we waited for all opened file descriptors to the terminal to be closed. This caused problem when e.g. running "sleep 900 &" and then exiting the shell, with sleep keeping the session alive and had to be killed manually (killing the process group did not help - the shell had already exited and was in zombie state). This is also what most other terminal emulators do. Relatedly, switch to sending SIGKILL to force quit a session instead of SIGHUP, since SIGHUP can be ignored.
This commit is contained in:
@@ -40,15 +40,6 @@ final class JNI {
|
||||
*/
|
||||
public static native int waitFor(int processId);
|
||||
|
||||
/**
|
||||
* Send SIGHUP to a process group.
|
||||
*
|
||||
* There exists a kill(2) system call wrapper in {@link android.os.Process#sendSignal(int, int)}, but that makes a
|
||||
* "if (pid > 0)" check so cannot be used for sending to a process group:
|
||||
* https://android.googlesource.com/platform/frameworks/base/+/donut-release/core/jni/android_util_Process.cpp
|
||||
*/
|
||||
public static native void hangupProcessGroup(int processId);
|
||||
|
||||
/** Close a file descriptor through the close(2) system call. */
|
||||
public static native void close(int fileDescriptor);
|
||||
|
||||
|
@@ -1,5 +1,13 @@
|
||||
package com.termux.terminal;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -9,11 +17,6 @@ import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A terminal session, consisting of a process coupled to a terminal interface.
|
||||
* <p>
|
||||
@@ -190,10 +193,6 @@ public final class TerminalSession extends TerminalOutput {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore, just shutting down.
|
||||
} finally {
|
||||
// Now wait for process exit:
|
||||
int processExitCode = JNI.waitFor(mShellPid);
|
||||
mMainThreadHandler.sendMessage(mMainThreadHandler.obtainMessage(MSG_PROCESS_EXITED, processExitCode));
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
@@ -213,7 +212,16 @@ public final class TerminalSession extends TerminalOutput {
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
new Thread("TermSessionWaiter[pid=" + mShellPid + "]") {
|
||||
@Override
|
||||
public void run() {
|
||||
int processExitCode = JNI.waitFor(mShellPid);
|
||||
mMainThreadHandler.sendMessage(mMainThreadHandler.obtainMessage(MSG_PROCESS_EXITED, processExitCode));
|
||||
}
|
||||
}.start();
|
||||
|
||||
}
|
||||
|
||||
/** Write data to the shell process. */
|
||||
@Override
|
||||
@@ -273,20 +281,16 @@ public final class TerminalSession extends TerminalOutput {
|
||||
notifyScreenUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish this terminal session. Frees resources used by the terminal emulator and closes the attached
|
||||
* <code>InputStream</code> and <code>OutputStream</code>.
|
||||
*/
|
||||
public void finishIfRunning() {
|
||||
if (isRunning()) {
|
||||
JNI.hangupProcessGroup(mShellPid);
|
||||
// Stop the reader and writer threads, and close the I/O streams. Note that
|
||||
// cleanupResources() will be run later.
|
||||
mTerminalToProcessIOQueue.close();
|
||||
mProcessToTerminalIOQueue.close();
|
||||
JNI.close(mTerminalFileDescriptor);
|
||||
}
|
||||
}
|
||||
/** Finish this terminal session by sending SIGKILL to the shell. */
|
||||
public void finishIfRunning() {
|
||||
if (isRunning()) {
|
||||
try {
|
||||
Os.kill(mShellPid, OsConstants.SIGKILL);
|
||||
} catch (ErrnoException e) {
|
||||
Log.w("termux", "Failed sending SIGKILL: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Cleanup resources when the process exits. */
|
||||
void cleanupResources(int exitStatus) {
|
||||
|
@@ -208,11 +208,6 @@ JNIEXPORT int JNICALL Java_com_termux_terminal_JNI_waitFor(JNIEnv* TERMUX_UNUSED
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_hangupProcessGroup(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint procId)
|
||||
{
|
||||
killpg(procId, SIGHUP);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_close(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fileDescriptor)
|
||||
{
|
||||
close(fileDescriptor);
|
||||
|
Reference in New Issue
Block a user