Skip to content

nohup: make the substitute stdin unreadable like GNU - #14655

Open
costajohnt wants to merge 1 commit into
uutils:mainfrom
costajohnt:fix/nohup-stdin-unreadable
Open

costajohnt wants to merge 1 commit into
uutils:mainfrom
costajohnt:fix/nohup-stdin-unreadable

Conversation

@costajohnt

Copy link
Copy Markdown
Contributor

When stdin is a terminal, nohup replaces it with /dev/null. We opened it read-only, so a command that went on to read from stdin got a silent EOF and exited 0:

$ nohup cat; echo $?
nohup: ignoring input and appending output to 'nohup.out'
0

GNU opens /dev/null write-only on purpose. From the manual: "Make the substitute file descriptor unreadable, so that commands that mistakenly attempt to read from standard input can report an error." Under GNU nohup the same command exits 1 and nohup.out holds cat: stdin: Bad file descriptor.

This change opens /dev/null with OpenOptions::new().write(true) in replace_fds() so a read on the substitute stdin fails with EBADF, matching GNU. stdout and stderr handling is unchanged.

The Windows side (platform/windows.rs) uses Stdio::null() for the child's stdin and is left as is; I did not find an equivalent of an unreadable handle there.

Testing:

  • New test_nohup_replaced_stdin_is_not_readable in tests/by-util/test_nohup.rs runs nohup cat under terminal_simulation(true), asserts exit status 1 and that nohup.out contains Bad file descriptor. It fails on main (exit 0) and passes with this change. Gated on the same target set as the sibling pty tests (apple, linux, android, freebsd, openbsd).
  • cargo test --features nohup --no-default-features --test tests -- test_nohup: 8 passed on macOS.
  • cargo fmt --all -- --check, cargo clippy -p uu_nohup --all-targets -- -D warnings, cargo clippy --features nohup --no-default-features --all-targets -- -D warnings: clean.
  • Manual check with script -q /dev/null on macOS: nohup cat and nohup gdate --file - both now exit 1 with the read error in nohup.out, same as gnohup.
  • GNU tests/misc/nohup.sh never reads stdin after the redirection, so no GNU test result should change. Not run locally (Linux only).

Fixes #14556

Reproduces against GNU coreutils 9.11 on Linux and macOS (gnohup cat under a pty exits 1 with cat: stdin: Bad file descriptor). The Cygwin report in the issue thread that could not reproduce was on GNU 9.0.

When stdin is a terminal, nohup replaces it with /dev/null. It was
opened read-only, so a command that went on to read stdin got a silent
EOF and exited 0 (`nohup cat`, `nohup date --file -`).

GNU opens /dev/null write-only on purpose: "Make the substitute file
descriptor unreadable, so that commands that mistakenly attempt to read
from standard input can report an error." Do the same, so such a read
fails with EBADF and the command exits 1 as it does under GNU nohup.

Fixes uutils#14556
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/tail/tail-n0f is now being skipped but was previously passing.
Congrats! The gnu test tests/expand/bounded-memory is now passing!
Note: The gnu test tests/env/env-signal-handler was skipped on 'main' but is now failing.

@oech3

oech3 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

There is a file named as NUL on Windows. unix needs to open /dev/null instead of Stdio::null() for the case /dev is not mounted. I'm not sure if we can fail to open NUL, or have a bug suggested by you on Windows.

// EOF (GNU opens /dev/null write-only). Since nohup execs the command, the
// exit status is the command's own.
#[test]
#[cfg(any(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not cfg(unix)?

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.

nohup: programs that are waiting for stdin exit with 0 instead of 1

2 participants