Comparing 4.1.2...4.1.3 · jline/jline3 (original) (raw)
Commits on May 23, 2026
Commits on May 26, 2026
- fix: clear ISIG in enterRawMode so Ctrl+C reaches raw-mode readers (f…
…ixes #1900)
After #1871 set VMIN=1/VTIME=0, Ctrl+C during DefaultPrompter.prompt()
hangs the JVM because ISIG is still set: the kernel consumes the byte as
SIGINT instead of delivering 0x03 to the input buffer, and the blocking
read never returns.
Clear ISIG in enterRawMode() to match POSIX cfmakeraw(3). Add an
INTERRUPT widget to LineReaderImpl bound to VINTR so that Ctrl+C typed
at the terminal still triggers UserInterruptException through the
keymap rather than through the (now-absent) SIGINT signal.
Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history
Commits on May 27, 2026
- Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history
Commits on May 28, 2026
- fix: terminal.close() blocks when pump thread is reading stdin (#1909)
On macOS, a pump thread blocked in a native read() on a tty can prevent
tcsetattr() from completing, causing terminal.close() to hang until the
user presses ENTER. Fix by switching to non-canonical mode with
VMIN=0/VTIME=1 before shutdown, which forces the blocked read() to time
out within 100 ms so the pump thread can exit cleanly before original
terminal attributes are restored.
Also improve NonBlockingInputStreamImpl and NonBlockingReaderImpl
shutdown: set threadIsReading=false, interrupt the thread, and join
with a timeout so close() reliably stops the pump thread. - fix: ensure pump thread shutdown is robust on close
- AbstractUnixSysTerminal: wrap VMIN/VTIME unblock sequence in
try-finally so input.shutdown() runs even if doGetAttributes()
or doSetAttributes() throws - NonBlockingInputStreamImpl/ReaderImpl: close the wrapped stream
before shutdown/join so the native read() is unblocked before
we wait for the pump thread to exit
- refactor: extract NonCloseable stream wrappers and add lifecycle tests
Extract NonCloseableInputStream and NonCloseableOutputStream from
DumbTerminalProvider into org.jline.utils for reuse. Apply them in
AbstractUnixSysTerminal to prevent closing shared FileDescriptors
(stdin/stdout/stderr) when the terminal is closed.
Add timeout logging to pump thread shutdown in NonBlockingInputStreamImpl
and NonBlockingReaderImpl. Add comprehensive tests for stream wrapper
behavior and pump thread lifecycle. - fix: wrap ExecPty system streams with NonCloseable wrappers
ExecPty.doGetSlaveInput() and getSlaveOutput() returned raw
FileInputStream/FileOutputStream on shared FileDescriptors when used
as a system terminal. Closing the terminal would close the shared
FDs, breaking System.in/out/err for the rest of the JVM.
Wrap the system stream cases with NonCloseableInputStream and
NonCloseableOutputStream, matching AbstractUnixSysTerminal and
DumbTerminalProvider. Device-file paths are left unwrapped since
those are non-shared FDs. - refactor: remove VMIN/VTIME unblock sequence from doClose()
The VMIN/VTIME trick cannot reliably unblock a native read() that is
already in progress — tcsetattr only affects the next read call, not
the current one. The NonCloseable wrappers are the actual fix: they
prevent FileDescriptor.close0() from being called, which eliminates
the macOS deadlock. The pump thread exits on its next iteration once
the current read completes naturally. - fix: reduce shutdown join timeout and prevent double-wait
Reduce the thread join timeout from 500ms to 50ms — the thread either
exits promptly (when waiting) or is stuck in a native read (where no
timeout helps). Setting thread = null after join prevents the second
shutdown() call in the close chain from waiting again. - refactor: extract PumpThread to deduplicate thread lifecycle management
NonBlockingInputStreamImpl and NonBlockingReaderImpl had identical
startReadingThreadIfNeeded(), shutdown(), and thread management fields.
Extract into a shared PumpThread helper that both classes delegate to. - refactor: move run loop into PumpThread to further reduce duplication
The run() method was still duplicated between NonBlockingInputStreamImpl
and NonBlockingReaderImpl. Move the loop into PumpThread.runLoop() with
IoReader and ResultHandler callbacks. Each Impl class now has a one-liner
run() that delegates to pump.runLoop(). - fix: address SonarCloud issues in PumpThread
Store lock as a field instead of passing as method parameter (S2445).
Use notifyAll instead of notify (S2446). Re-interrupt on
InterruptedException in runLoop (S2142).
Configuration menu
Browse the repository at this point in the history
- Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history - Configuration menu
Browse the repository at this point in the history - fix: fix command argument parsing in DefaultCommandDispatcher (#1924)
- Fix command argument parsing
- Fix potential resource leak by handling all possible unchecked exceptions.
- Fix test as per #1238 (comment)
- fix: resolve rebase conflicts and address review feedback
- Fix leftover conflict markers from rebase onto master
- Remove redundant parser creation in ShellBuilder — pass this.parser
directly since DefaultCommandDispatcher handles null - Quote script path in sourceCommand test to handle Windows backslashes
- fix: share single parser instance between dispatcher and reader
Restore the shared parser creation in ShellBuilder.build() so that
DefaultCommandDispatcher and LineReader use the same Parser instance
when none is explicitly configured.
Co-authored-by: Elec332 6115944+Elec332@users.noreply.github.com
Configuration menu
Browse the repository at this point in the history