Skip to content

tee: handle short writes to stdout correctly #14981

Description

@mattsu2020

tee does not correctly handle short writes to stdout when stdout is a regular file on Linux.

The GNU tee/short-write.sh test expects short writes to be retried until the remaining data is written, but the current implementation uses the splice path for regular-file stdout, bypassing the injected write(2) short writes.

We should ensure that short writes to regular-file stdout are handled correctly.

Related to #14705.

Activity

  1. self-assigned this
    on Sep 30, 2026
  2. xtqqczze commented on Sep 30, 2026

    @xtqqczze
    Collaborator

    taken by @mattsu2020

  3. oech3 commented on Sep 30, 2026

    @oech3
    Contributor

    Difference of used syscall is not a problem if the used syscall is an optional dependency.
    We can patch GnuTests in this case to support our syscall.

  4. mattsu2020 commented on Sep 30, 2026

    @mattsu2020
    ContributorAuthor

    Difference of used syscall is not a problem if the used syscall is an optional dependency. We can patch GnuTests in this case to support our syscall.

    Should we update the GNU test to use splice instead?

  5. oech3 commented on Sep 30, 2026

    @oech3
    Contributor

    I think so. But it is bit tricky to the test meaningful for splice(2) path. I'd like to patch to fail splice path at fallback to write path at a moment.

    It is done by adding -e fault=splice.

  6. oech3 commented on Sep 30, 2026

    @oech3
  7. removed their assignment
    on Sep 30, 2026
  8. oech3 commented on Sep 30, 2026

    @oech3
    Contributor

    We could use named pipe with 1 byte remain to cause short-write. But it would be too complex.

  9. oech3 commented on Oct 7, 2026

    @oech3
    Contributor

    I think it is impossible to do same strace test for splice(2) since strace is a tool to modify returned value, not a len passed to splice(2).

  10. mattsu2020 commented on Oct 7, 2026

    @mattsu2020
    ContributorAuthor

    I think it is impossible to do same strace test for splice(2) since strace is a tool to modify returned value, not a len passed to splice(2).

    How about changing the test to something like the following?

    strace -qqq -o /dev/null --trace-fds=1 -e trace=write,splice \
      -e fault=splice \
      -e inject=write:retval=1:when=1..5 "$@"
    
  11. oech3 commented on Oct 7, 2026

    @oech3
  12. oech3 commented on Oct 7, 2026

    @oech3
    Contributor

    #14981 (comment) tests write code path only.

  13. oech3 commented on Oct 7, 2026

    @oech3
  14. oech3 commented on Oct 7, 2026

    @oech3
    Contributor

    OK. So splice(2) and write(2) are very different.

    • retval=1 for write(2) means write(2) returns 1 without actually writing. So next read(2) consumes buffer. Then we lost "a". So we lost "a" by previous read(2). It is expected and used at GnuTests.
    • retval=1 for splice(2) means splice(2) returns 1 without actually sending. So pipe buffer is NOT changed. It is "correct" behaviour. Then we see "a" after all retval'ed call finished since it is still in pipe buffer.
  15. oech3 commented on Oct 8, 2026

    @oech3
    Contributor

    I fixed the previous comment about read.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions