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);
|
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. */
|
/** Close a file descriptor through the close(2) system call. */
|
||||||
public static native void close(int fileDescriptor);
|
public static native void close(int fileDescriptor);
|
||||||
|
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
package com.termux.terminal;
|
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.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -9,11 +17,6 @@ import java.lang.reflect.Field;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.UUID;
|
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.
|
* A terminal session, consisting of a process coupled to a terminal interface.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -190,10 +193,6 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Ignore, just shutting down.
|
// Ignore, just shutting down.
|
||||||
} finally {
|
|
||||||
// Now wait for process exit:
|
|
||||||
int processExitCode = JNI.waitFor(mShellPid);
|
|
||||||
mMainThreadHandler.sendMessage(mMainThreadHandler.obtainMessage(MSG_PROCESS_EXITED, processExitCode));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
@@ -213,7 +212,16 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
}.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. */
|
/** Write data to the shell process. */
|
||||||
@Override
|
@Override
|
||||||
@@ -273,20 +281,16 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
notifyScreenUpdate();
|
notifyScreenUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Finish this terminal session by sending SIGKILL to the shell. */
|
||||||
* Finish this terminal session. Frees resources used by the terminal emulator and closes the attached
|
public void finishIfRunning() {
|
||||||
* <code>InputStream</code> and <code>OutputStream</code>.
|
if (isRunning()) {
|
||||||
*/
|
try {
|
||||||
public void finishIfRunning() {
|
Os.kill(mShellPid, OsConstants.SIGKILL);
|
||||||
if (isRunning()) {
|
} catch (ErrnoException e) {
|
||||||
JNI.hangupProcessGroup(mShellPid);
|
Log.w("termux", "Failed sending SIGKILL: " + e.getMessage());
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Cleanup resources when the process exits. */
|
/** Cleanup resources when the process exits. */
|
||||||
void cleanupResources(int exitStatus) {
|
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)
|
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_close(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fileDescriptor)
|
||||||
{
|
{
|
||||||
close(fileDescriptor);
|
close(fileDescriptor);
|
||||||
|
Reference in New Issue
Block a user