Skip to content

Fixed: Fix locale sensitive case conversion, byte truncation, selection offset, main thread transcript building and add phantom processes docs - #5248

Open
BuildWithAni wants to merge 9 commits into
termux:masterfrom
BuildWithAni:fix/locale-result-sender-selection-fixes
Open

Fixed: Fix locale sensitive case conversion, byte truncation, selection offset, main thread transcript building and add phantom processes docs#5248
BuildWithAni wants to merge 9 commits into
termux:masterfrom
BuildWithAni:fix/locale-result-sender-selection-fixes

Conversation

@BuildWithAni

Copy link
Copy Markdown

Fixes several bugs found while reviewing the codebase, across app, terminal-view and termux-shared modules.

  1. Locale-sensitive toLowerCase()/toUpperCase() (8 files, termux-shared + app). Calls without an explicit locale used the device locale, so on Turkish (tr-TR) devices "CTRL+I" lowercased to "ctrı+ı" and stopped matching "ctrl", breaking session shortcut parsing, property map lookups, filename sanitizing and MIME type detection. All calls now use Locale.ROOT.

  2. getTruncatedCommandOutput() truncates by characters, not bytes (DataUtils.java). The limit constants (TRANSACTION_SIZE_LIMIT_IN_BYTES = 100KB, LOGGER_ENTRY_MAX_SAFE_PAYLOAD, etc.) are byte limits, but truncation counted characters. With multibyte UTF-8 output (CJK, emoji, up to 4 bytes/char) the result could still exceed the binder transaction limit by 4x and cause TransactionTooLargeException when sending command results via pending intents. Truncation is now byte-based, never splitting a multi-byte character.

  3. Hardcoded 40 px offset in TerminalView.getCursorY() (terminal-view). The 40 was a leftover finger-offset from the old toggleSelectingText() code, but getCursorY() is now used unconditionally by TextSelectionCursorController.updatePosition() when dragging selection handles — and it ignored the font size entirely, so handles tracked the wrong row at any non-default font size. It now uses mRenderer.mFontLineSpacingAndAscent, matching getColumnAndRow().

  4. Transcript building on the main thread (TermuxTerminalViewClient.java). shareSessionTranscript(), showUrlSelection() and reportIssueFromTranscript() built the full terminal scrollback string (and ran URL extraction regexes) on the UI thread — an ANR risk with large scrollback. Transcript building now runs on a background thread with the UI work posted back via runOnUiThread().

  5. Phantom processes docs page (docs/ + README.md). The README notice promised "A proper docs page will be added later". Added docs/en/apps/termux/phantom-processes.md covering how to detect kills via logcat, how to check the max_phantom_processes limit, and how to disable phantom/excessive-CPU process trimming per Android version (12, 12L/13, 14+), and linked it from the README notice.

All modules compile successfully:

BUILD SUCCESSFUL

Unit tests for terminal-emulator and app pass:

BUILD SUCCESSFUL

…ux-shared

- Fixed: Send SIGKILL to process in AppShell.killIfExecuting() unconditionally since setStateFailed() sets state to FAILED and isExecuting() will always be false after that, so SIGKILL was never sent
- Fixed: Return early in AmSocketServer.processAmClient() after sending error result to client so that a bogus success result frame is not sent afterwards
- Fixed: Use client socket fd instead of server socket fd in LocalClientSocket.available() to check for available data
… bound

- Fixed: Implement onSessionFinished() in TermuxTerminalSessionServiceClient to remove finished sessions when the TermuxActivity is not bound to the TermuxService, since TermuxTerminalSessionActivityClient was the only client that processed finished sessions. Sessions that finished while the activity was unbound were never removed, plugin results were never sent back and the notification was never updated, so the service would not stop
- Fixed: Remove the global layout listener of FullScreenWorkAround when activity is destroyed and deduplicate instances on re-apply so that the listener does not keep running and hold activity references after the activity has been destroyed
- Fixed: Remove stale resize style indexing bug comment and guard against unpaired high surrogate at end of row in TerminalBuffer.resize() so that rows ending with an unpaired high surrogate do not read mText out of bounds
- Fixed: Validate OSC 104 color index before resetting it and restructure the parameter loop so that malformed input does not crash with ArrayIndexOutOfBoundsException or StringIndexOutOfBoundsException
- Fixed: Clamp DECCARA and DECRARA rectangle coordinates to effective margins so that bottom and right bounds never exceed the screen dimensions and the last row and column are not excluded
- Fixed: Move cursor to lower-left corner of screen instead of top row in ESC F handler
…shebang interpreter arguments

- Fixed: Guard against reading past the end of the string in ArgumentTokenizer when a double quoted argument ends with a backslash so that a StringIndexOutOfBoundsException is not thrown
- Fixed: Preserve shebang interpreter arguments like the -e flag of #!/bin/bash -e and the interpreter name of #!/usr/bin/env bash in TermuxShellUtils.setupShellCommandArguments() instead of dropping everything after the first whitespace
@robertkirkman

Copy link
Copy Markdown
Member

Thank you for the contributions,

many of these problems may be fixed in an upcoming version of Termux and the code edited may be replaced with other code, so you should be prepared to wait and eventually rebase the PR when the update comes.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants