From a0fa51eb926b478374599320c59c2dde5802cf15 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Wed, 26 Oct 2016 02:26:44 +0200 Subject: [PATCH] Start work on background jobs --- .../java/com/termux/app/BackgroundJob.java | 84 +++++++++++++------ .../java/com/termux/app/TermuxService.java | 54 +++++------- 2 files changed, 76 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/com/termux/app/BackgroundJob.java b/app/src/main/java/com/termux/app/BackgroundJob.java index 2be30101..fd54b5bc 100644 --- a/app/src/main/java/com/termux/app/BackgroundJob.java +++ b/app/src/main/java/com/termux/app/BackgroundJob.java @@ -7,55 +7,71 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; +import java.util.Arrays; /** * A background job launched by Termux. */ public final class BackgroundJob { - private static final String LOG_TAG = "termux-background"; + private static final String LOG_TAG = "termux-job"; final Process mProcess; - public BackgroundJob(File cwd, File fileToExecute, String[] args) throws IOException { - String[] env = buildEnvironment(false, cwd.getAbsolutePath()); + public BackgroundJob(String cwd, String fileToExecute, final String[] args) { + String[] env = buildEnvironment(false, cwd); + if (cwd == null) cwd = TermuxService.HOME_PATH; - String[] progArray = new String[args.length + 1]; + String[] modifiedArgs; + if (args == null) { + modifiedArgs = new String[]{fileToExecute}; + } else { + modifiedArgs = new String[args.length + 1]; + modifiedArgs[0] = fileToExecute; + System.arraycopy(args, 0, modifiedArgs, 1, args.length); + } + final String[] progArray = modifiedArgs; - mProcess = Runtime.getRuntime().exec(progArray, env, cwd); - - new Thread() { - @Override - public void run() { - while (true) { - try { - int exitCode = mProcess.waitFor(); - if (exitCode == 0) { - Log.i(LOG_TAG, "exited normally"); - return; - } else { - Log.i(LOG_TAG, "exited with exit code: " + exitCode); - } - } catch (InterruptedException e) { - // Ignore. - } - } - } - }.start(); + final String processDescription = Arrays.toString(progArray); + + Process process; + try { + process = Runtime.getRuntime().exec(progArray, env, new File(cwd)); + } catch (IOException e) { + mProcess = null; + // TODO: Visible error message? + Log.e(LOG_TAG, "Failed running background job: " + processDescription, e); + return; + } + mProcess = process; + final int pid = getPid(mProcess); new Thread() { @Override public void run() { + Log.i(LOG_TAG, "[" + pid + "] starting: " + processDescription); InputStream stdout = mProcess.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stdout, StandardCharsets.UTF_8)); String line; try { // FIXME: Long lines. while ((line = reader.readLine()) != null) { - Log.i(LOG_TAG, line); + Log.i(LOG_TAG, "[" + pid + "] stdout: " + line); } } catch (IOException e) { + Log.e(LOG_TAG, "Error reading output", e); + } + + try { + int exitCode = mProcess.waitFor(); + if (exitCode == 0) { + Log.i(LOG_TAG, "[" + pid + "] exited normally"); + } else { + Log.w(LOG_TAG, "[" + pid + "] exited with code: " + exitCode); + } + } catch (InterruptedException e) { // Ignore. } } @@ -71,7 +87,7 @@ public final class BackgroundJob { try { // FIXME: Long lines. while ((line = reader.readLine()) != null) { - Log.e(LOG_TAG, line); + Log.i(LOG_TAG, "[" + pid + "] stderr: " + line); } } catch (IOException e) { // Ignore. @@ -80,7 +96,7 @@ public final class BackgroundJob { }; } - public String[] buildEnvironment(boolean failSafe, String cwd) { + public static String[] buildEnvironment(boolean failSafe, String cwd) { new File(TermuxService.HOME_PATH).mkdirs(); if (cwd == null) cwd = TermuxService.HOME_PATH; @@ -109,4 +125,18 @@ public final class BackgroundJob { } } + public static int getPid(Process p) { + int pid = -1; + + try { + Field f = p.getClass().getDeclaredField("pid"); + f.setAccessible(true); + pid = f.getInt(p); + f.setAccessible(false); + } catch (Throwable e) { + pid = -1; + } + return pid; + } + } diff --git a/app/src/main/java/com/termux/app/TermuxService.java b/app/src/main/java/com/termux/app/TermuxService.java index 34e21bba..f7489351 100644 --- a/app/src/main/java/com/termux/app/TermuxService.java +++ b/app/src/main/java/com/termux/app/TermuxService.java @@ -119,21 +119,26 @@ public final class TermuxService extends Service implements SessionChangedCallba String executablePath = (executableUri == null ? null : executableUri.getPath()); String[] arguments = (executableUri == null ? null : intent.getStringArrayExtra(EXTRA_ARGUMENTS)); String cwd = intent.getStringExtra(EXTRA_CURRENT_WORKING_DIRECTORY); - TerminalSession newSession = createTermSession(executablePath, arguments, cwd, false); - // Transform executable path to session name, e.g. "/bin/do-something.sh" => "do something.sh". - if (executablePath != null) { - int lastSlash = executablePath.lastIndexOf('/'); - String name = (lastSlash == -1) ? executablePath : executablePath.substring(lastSlash + 1); - name = name.replace('-', ' '); - newSession.mSessionName = name; + if (intent.getBooleanExtra("com.termux.execute.background", false)) { + new BackgroundJob(cwd, executablePath, arguments); + } else { + TerminalSession newSession = createTermSession(executablePath, arguments, cwd, false); + + // Transform executable path to session name, e.g. "/bin/do-something.sh" => "do something.sh". + if (executablePath != null) { + int lastSlash = executablePath.lastIndexOf('/'); + String name = (lastSlash == -1) ? executablePath : executablePath.substring(lastSlash + 1); + name = name.replace('-', ' '); + newSession.mSessionName = name; + } + + // Make the newly created session the current one to be displayed: + TermuxPreferences.storeCurrentSession(this, newSession); + + // Launch the main Termux app, which will now show to current session: + startActivity(new Intent(this, TermuxActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } - - // Make the newly created session the current one to be displayed: - TermuxPreferences.storeCurrentSession(this, newSession); - - // Launch the main Termux app, which will now show to current session: - startActivity(new Intent(this, TermuxActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } else if (action != null) { Log.e(EmulatorDebug.LOG_TAG, "Unknown TermuxService action: '" + action + "'"); } @@ -236,28 +241,7 @@ public final class TermuxService extends Service implements SessionChangedCallba if (cwd == null) cwd = HOME_PATH; - final String termEnv = "TERM=xterm-256color"; - final String homeEnv = "HOME=" + HOME_PATH; - final String prefixEnv = "PREFIX=" + PREFIX_PATH; - final String androidRootEnv = "ANDROID_ROOT=" + System.getenv("ANDROID_ROOT"); - final String androidDataEnv = "ANDROID_DATA=" + System.getenv("ANDROID_DATA"); - // EXTERNAL_STORAGE is needed for /system/bin/am to work on at least - // Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3. - final String externalStorageEnv = "EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"); - String[] env; - if (failSafe) { - // Keep the default path so that system binaries can be used in the failsafe session. - final String pathEnv = "PATH=" + System.getenv("PATH"); - env = new String[]{termEnv, homeEnv, prefixEnv, androidRootEnv, androidDataEnv, pathEnv, externalStorageEnv}; - } else { - final String ps1Env = "PS1=$ "; - final String ldEnv = "LD_LIBRARY_PATH=" + PREFIX_PATH + "/lib"; - final String langEnv = "LANG=en_US.UTF-8"; - final String pathEnv = "PATH=" + PREFIX_PATH + "/bin:" + PREFIX_PATH + "/bin/applets"; - final String pwdEnv = "PWD=" + cwd; - - env = new String[]{termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv}; - } + String[] env = BackgroundJob.buildEnvironment(failSafe, cwd); String shellName; if (executablePath == null) {