Skip to content

Terminate at.at() stdin with a trailing newline#69768

Open
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-58510
Open

Terminate at.at() stdin with a trailing newline#69768
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-58510

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

at.at() builds the command string it pipes to at via cmd.run(..., stdin=stdin, python_shell=False) but never terminates it with a newline. This PR appends a single trailing newline after the stdin is assembled, covering both the tagged (tag=) and untagged branches in one place.

What issues does this PR fix or reference?

Fixes #58510

Previous Behavior

On distributions that ship the Fedora-patched at (Fedora/RHEL/CentOS; Fedora at-3.2.2-shell.patch, Red Hat BZ 486844 / BZ 2070450), at writes its job delimiter with fprintf(fp, "marcinDELIMITER%08lx\n", i) immediately after the last byte of stdin. Because Salt sent no trailing newline, the delimiter concatenated onto the final command, e.g. shutdown -r nowmarcinDELIMITER7f94e9f4, producing an invalid job that silently never executed. Reproduced by the maintainer and by a bare subprocess repro in the issue thread.

New Behavior

A trailing newline is appended to the stdin, so the delimiter lands on its own line and the command runs. This matches the newline a normal echo cmd | at now shell pipe already sends, so behaviour is unchanged on Debian/Ubuntu/BSD and on any non-patched at.

Merge requirements satisfied?

  • Docs (not applicable - no user-facing doc change)
  • Changelog entry (changelog/58510.fixed.md)
  • Tests written and described - added a direct-altitude test asserting the piped stdin ends with a newline for both the tagged and untagged branches (production-exact at.at('12:05am', '/sbin/reboot', tag='reboot')), an inverse test asserting the command payload is preserved and not double-newlined (passes with and without the fix), and peripheral coverage of the command-list and runas/python_shell handling.

[NOTE] Please review Salt's Contributing Guide for best practices.

Commits signed with GPG?: No

at.at() piped the command to `at` without a trailing newline. Distro-patched
`at` on Fedora/RHEL/CentOS (Fedora at-3.2.2-shell.patch, BZ 486844) writes its
job delimiter immediately after the last stdin byte, so with no trailing
newline the delimiter concatenates onto the final command (e.g.
`shutdown -r nowmarcinDELIMITER7f94e9f4`), producing a job that never runs.

Append a single newline after building stdin, covering both the tagged and
untagged branches. This matches the newline a normal `echo cmd | at now` pipe
already sends, so it is benign on Debian/Ubuntu/BSD.

Fixes saltstack#58510
@ggiesen ggiesen requested a review from a team as a code owner July 10, 2026 17:55
@charzl charzl self-assigned this Jul 10, 2026
@dwoz dwoz added the test:full Run the full test suite label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants