Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/changelog/3.0.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Minor cleanups and documentation fixes.

- Fixed issue during TUI app initialization where debug logs would be discarded
and warnings would fail to display correctly.
- Fix Issue where `SystemError: buffer overflow` was encountered during CLI tasks
on Python 3.14 in some specific circumstances, due to an upstream Fabric bug.

## Documentation

Expand Down
1 change: 1 addition & 0 deletions docs/source/spelling_wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ solaris
sortable
sqlite
sshd
stdin
stdout
subclass
subclasses
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "exosphere-cli"
version = "3.0.1.dev2"
version = "3.0.1.dev3"
description = "CLI/TUI driven patch reporting for remote Unix-like systems."
readme = "README.md"
authors = [
Expand Down
13 changes: 10 additions & 3 deletions src/exosphere/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,19 @@ def connection(self) -> Connection:
Connection objects are recycled if already created.

The connection is setup with an environment override that
forces two things on all commands run through it:
forces three things on all commands run through it:

1. The locale is set to the configured value (default is C)
2. The command is explicitly ran under /bin/sh (POSIX)
3. Local stdin is never forwarded to the remote command

This allows consistent, deterministic output and behavior,
regardless of the user's login shell or locale.
The first two allow consistent, deterministic output and
behavior, regardless of the user's login shell or locale.

The third avoids contention for the local terminal, which has
a history of triggering bugs in Fabric/Invoke, and is not
needed at all for operation, since all Exosphere commands
are fully expected to be non-interactive.

If you work with Host objects directly, make sure to call
`host.close()` when done with operations (such as discover,
Expand All @@ -323,6 +329,7 @@ def connection(self) -> Connection:
overrides={
"runners": {"remote": ExosphereRemote},
"exosphere_locale": self.ssh_locale,
"run": {"in_stream": False},
}
),
}
Expand Down
16 changes: 16 additions & 0 deletions tests/test_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,22 @@ def test_host_connection_locale_override(self, mocker, mock_connection):
config = mock_connection.call_args.kwargs["config"]
assert config.exosphere_locale == "C.UTF-8"

def test_host_connection_disables_stdin(self, mocker, mock_connection):
"""
The connection disables stdin forwarding, so that Fabric never spawns
a stdin handling thread contending over the local terminal.

This is in response to an upstream Fabric bug that can trigger
a buffer overflow on Python 3.14 when the local terminal is used
concurrently during discovery or refresh operations.
"""
host = Host(name="test_host", ip="127.0.0.8")

_ = host.connection

config = mock_connection.call_args.kwargs["config"]
assert config.run.in_stream is False

def test_host_config_sudo_policy(self, mocker):
"""
Test that the Host object uses the sudo policy from the configuration.
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.