diff --git a/docs/source/changelog/3.0.1.md b/docs/source/changelog/3.0.1.md index 8e67799..3d7539e 100644 --- a/docs/source/changelog/3.0.1.md +++ b/docs/source/changelog/3.0.1.md @@ -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 diff --git a/docs/source/spelling_wordlist.txt b/docs/source/spelling_wordlist.txt index e87dc64..484176a 100644 --- a/docs/source/spelling_wordlist.txt +++ b/docs/source/spelling_wordlist.txt @@ -98,6 +98,7 @@ solaris sortable sqlite sshd +stdin stdout subclass subclasses diff --git a/pyproject.toml b/pyproject.toml index b6758d3..fe55250 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 = [ diff --git a/src/exosphere/objects.py b/src/exosphere/objects.py index be5926c..2b58784 100644 --- a/src/exosphere/objects.py +++ b/src/exosphere/objects.py @@ -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, @@ -323,6 +329,7 @@ def connection(self) -> Connection: overrides={ "runners": {"remote": ExosphereRemote}, "exosphere_locale": self.ssh_locale, + "run": {"in_stream": False}, } ), } diff --git a/tests/test_objects.py b/tests/test_objects.py index 2ad01b5..a1696e2 100644 --- a/tests/test_objects.py +++ b/tests/test_objects.py @@ -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. diff --git a/uv.lock b/uv.lock index 1cbb104..33d7d21 100644 --- a/uv.lock +++ b/uv.lock @@ -648,7 +648,7 @@ wheels = [ [[package]] name = "exosphere-cli" -version = "3.0.1.dev2" +version = "3.0.1.dev3" source = { editable = "." } dependencies = [ { name = "cyclopts" },