Skip to content

feat: terminal fail safe#2144

Draft
RohitKushvaha01 wants to merge 1 commit into
Acode-Foundation:mainfrom
RohitKushvaha01:main
Draft

feat: terminal fail safe#2144
RohitKushvaha01 wants to merge 1 commit into
Acode-Foundation:mainfrom
RohitKushvaha01:main

Conversation

@RohitKushvaha01
Copy link
Copy Markdown
Member

@RohitKushvaha01 RohitKushvaha01 commented Jun 1, 2026

Closes #2084

@RohitKushvaha01 RohitKushvaha01 marked this pull request as draft June 1, 2026 10:39
@github-actions github-actions Bot added the translations Anything related to Translations Whether a Issue or PR label Jun 1, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 1, 2026

Greptile Summary

This PR adds a "failsafe mode" setting that launches the AXS terminal server directly via the system linker, bypassing proot — intended for devices where proot fails. To support this, init-alpine.sh was refactored to run all one-time setup unconditionally, and Terminal.js/terminal.js were updated to pass the failsafeMode flag through to startAxs.

  • init-alpine.sh restructured: One-time init (chmod, motd, acode CLI, initrc) now runs before any argument checks. The --installing branch was simplified, but the timezone setup (ANDROID_TZ/etc/localtime) was accidentally dropped, meaning new installs will run Alpine in UTC.
  • Failsafe branch in Terminal.js: When failsafeMode=true, axs is launched via the architecture-appropriate system linker without proot; known issues with PID tracking and unquoted paths were flagged in prior review threads.
  • Settings wired end-to-end: terminalDefaults.js defaults failsafeMode to false, and terminalSettings.js exposes the toggle; non-English locale files received only the label key, not the info description.

Confidence Score: 3/5

The normal terminal path is broken and new Alpine installations will silently run in UTC instead of the device timezone.

The --installing branch drops the ANDROID_TZ timezone setup that was the only mechanism for giving Alpine the correct local time, affecting all new installations. Combined with the normal-mode axs startup regression flagged in a prior thread, both core code paths have active defects.

src/plugins/terminal/scripts/init-alpine.sh requires the most attention — the timezone removal and the removed axs startup are both in this file. src/plugins/terminal/www/Terminal.js also has open issues with PID tracking and unquoted paths in the failsafe command.

Important Files Changed

Filename Overview
src/plugins/terminal/scripts/init-alpine.sh Script restructured to run one-time init unconditionally; timezone setup was silently dropped from --installing branch, and axs server is no longer launched in normal mode (known issue from prior threads).
src/plugins/terminal/www/Terminal.js Adds failsafeMode parameter to startAxs; failsafe command writes the outer sh PID instead of the axs PID, and file paths are unquoted (both flagged in prior threads).
src/components/terminal/terminal.js Passes failsafeMode from terminal settings to startAxs; getTerminalSettings import is correct and failsafeMode defaults to false.
src/settings/terminalSettings.js Adds failsafeMode toggle to the settings UI; toast message is hardcoded in English and info key is missing from non-English locales (flagged in prior thread).
src/components/terminal/terminalDefaults.js Adds failsafeMode: false as a safe default in DEFAULT_TERMINAL_SETTINGS.
src/lang/en-us.json Adds failsafe mode and info-failsafeMode keys; non-English locales only received the label key (info key missing, flagged in prior thread).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[createSession] --> B{isAxsRunning?}
    B -- No --> C[getTerminalSettings]
    C --> D{failsafeMode?}
    D -- Yes --> E[startAxs with failsafeMode=true]
    D -- No --> F[startAxs with failsafeMode=false]
    E --> G["Executor.start sh\nchmod +x axs\necho $$ > pid\nlinker axs -c sh -i"]
    F --> H["Executor.start sh\nsource init-sandbox.sh"]
    H --> I["init-sandbox.sh to proot to init-alpine.sh"]
    I --> J["exec /bin/bash --rcfile /initrc\naxs not started"]
    G --> K["axs HTTP server running\nsh PID in pid file not axs PID"]
    B -- Yes --> L[Poll up to 10s]
    L --> M[createSession via HTTP]
    K --> M
Loading

Reviews (2): Last reviewed commit: "feat: terminal fail safe" | Re-trigger Greptile

Comment on lines +229 to +235
if [ "$1" = "--installing" ]; then
touch "$PREFIX/.configured"
exit 0
fi

# Fallback to bash if no command specified
exec /bin/bash --rcfile /initrc
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 axs server and pid file no longer started in normal mode

The old init-alpine.sh wrote echo "$$" > "$PREFIX/pid" and then launched "$PREFIX/axs" -c "bash --rcfile /initrc -i" in the no-args (normal terminal start) branch. The new code replaces both with exec /bin/bash --rcfile /initrc, which runs bash inside proot but never starts the axs HTTP server.

createSession() in terminal.js connects to http://localhost:{port}/terminals — which only works when axs is running. With no pid file, isAxsRunning() always returns false, so startAxs is called on every session open; the 10-second polling loop exhausts, a toast fires, and then the fetch to the axs endpoint fails. The terminal is effectively broken in the default (non-failsafe) mode after this change.

}).then(async (uuid) => {
await Executor.write(uuid, `source ${filesDir}/init-sandbox.sh ${installing ? "--installing" : ""}; exit`);
if (failsafeMode) {
await Executor.write(uuid, `chmod +x ${filesDir}/axs; echo $$ > ${filesDir}/pid; ${linker} ${filesDir}/axs -c "sh -i"; exit`);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unquoted ${filesDir} will break on paths containing spaces. All three uses should be double-quoted within the shell string.

Suggested change
await Executor.write(uuid, `chmod +x ${filesDir}/axs; echo $$ > ${filesDir}/pid; ${linker} ${filesDir}/axs -c "sh -i"; exit`);
await Executor.write(uuid, `chmod +x "${filesDir}/axs"; echo $$ > "${filesDir}/pid"; ${linker} "${filesDir}/axs" -c "sh -i"; exit`);

Comment on lines +71 to +73
if (failsafeMode) {
await Executor.write(uuid, `chmod +x ${filesDir}/axs; echo $$ > ${filesDir}/pid; ${linker} ${filesDir}/axs -c "sh -i"; exit`);
} else {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Failsafe mode: axs process is orphaned when stopAxs() is called

echo $$ > ${filesDir}/pid stores the PID of the outer sh shell (started by Executor.start). stopAxs() then does kill -KILL $(cat $PREFIX/pid), which kills that outer shell. However, the ${linker} ${filesDir}/axs child process is not in the same process group and is not covered by --kill-on-exit (that flag is proot-specific). On Android/Linux, killing a parent with SIGKILL orphans its children — axs survives.

On the next createSession(), isAxsRunning() finds the old sh PID dead and returns false, triggering another startAxs. The new axs instance attempts to bind the same port while the old orphaned instance still holds it, causing the new start to fail silently. Users end up with leaked axs processes accumulating across terminal restarts.

Consider writing the axs PID directly — e.g., start axs in the background, capture $!, write that to the pid file, and wait for it — so stopAxs kills the process that actually owns the port.

Comment on lines +296 to +298
if (key === "failsafeMode") {
toast("Restart terminal to apply changes");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hardcoded English toast and missing info-failsafeMode in non-English locales

toast("Restart terminal to apply changes") is not passed through the strings i18n map, so non-English users see English text. A corresponding key (e.g., "restart terminal to apply changes") should be added to all locale files and referenced via strings[...] here.

Additionally, every non-English locale file in this PR only received the "failsafe mode" key; none received "info-failsafeMode". The setting's info field will render as undefined for all non-English users.

@UnschooledGamer
Copy link
Copy Markdown
Member

Wow, Mini Termux-like.

@RohitKushvaha01
Copy link
Copy Markdown
Member Author

TODO: convert axs to a pie executable

@RohitKushvaha01
Copy link
Copy Markdown
Member Author

@greptileai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

translations Anything related to Translations Whether a Issue or PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Terminal FailSafe mode

2 participants