Bug 260938 - script(1) hangs when child doesn't read input fast enough
Summary: script(1) hangs when child doesn't read input fast enough
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 13.0-RELEASE
Hardware: Any Any
: --- Affects Only Me
Assignee: Konstantin Belousov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-01-04 20:25 UTC by наб
Modified: 2024-01-08 17:56 UTC (History)
4 users (show)

See Also:


Attachments
Above core dump, zstd compressed (26.00 KB, application/octet-stream)
2022-01-04 20:25 UTC, наб
no flags Details
Above ktrace output (25.98 KB, application/octet-stream)
2022-01-04 20:26 UTC, наб
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description наб 2022-01-04 20:25:14 UTC
Created attachment 230710 [details]
Above core dump, zstd compressed

If there's enough input and the child doesn't read it in fast enough, script(1) deadlocks on stdin to the child against the child writing to its stdout.

This is a regression from 4.4BSD-Lite, brought on by replacing the 2-process model (i.e.
  leader:       stdin -> master pty
    child:      master pty -> stdout/fscript
      subchild: the command
) with a single process and select(2); writes to the master pty don't seem to shard, and block forever; the child cannot continue because it's blocked on writing its own data.

This is the same bug as in util-linux's implementation (though that uses poll(2)), so please see this Debian bug for more words on the topic: https://bugs.debian.org/1003095

Attaching core I got after ^\ing and trace from 
  ktrace script /dev/null sh -c 'for i in $(seq 10); do echo $i; done; read -r a; echo a=$a' < lc
wherein lc is
  b64encode /lib/libc.so.7 /lib/libc.so.7  > lc
uname -a says "FreeBSD build 13.0-RELEASE-p4 FreeBSD 13.0-RELEASE-p4 #0: Tue Aug 24 07:33:27 UTC 2021     root@amd64-builder.daemonology.net:/usr/obj/usr/src/amd64.amd64/sys/GENERIC  amd64"
Comment 1 наб 2022-01-04 20:26:09 UTC
Created attachment 230711 [details]
Above ktrace output
Comment 2 Konstantin Belousov freebsd_committer freebsd_triage 2022-01-08 13:26:05 UTC
https://reviews.freebsd.org/D33789
Comment 3 commit-hook freebsd_committer freebsd_triage 2022-01-10 15:36:00 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee

commit c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-01-08 13:19:14 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-01-10 15:34:51 +0000

    script(1): work around slow reading child

    If child is slow reading from its input, or even completely stops doing
    the read, script(1) hangs in write(2) to the pts master waiting until
    there is a space in the terminal discipline buffer.  This also stops
    handling any outer io, as well as child output.

    Work around the problem by making pts master fd non-blocking, and be
    prepared for short writes to it.  The data to be written to master is
    buffered in the tailq which is processed when select(2) detects that
    master is ready for write.

    PR:     260938
    Reported by:    наб <nabijaczleweli@nabijaczleweli.xyz>
    See also:       https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1003095
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D33789

 usr.bin/script/script.c | 56 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 5 deletions(-)
Comment 4 commit-hook freebsd_committer freebsd_triage 2022-01-16 02:54:49 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=6c12b392280cf99380ad2897d37d46659e8a1d9a

commit 6c12b392280cf99380ad2897d37d46659e8a1d9a
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-01-08 13:19:14 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-01-15 12:55:32 +0000

    script(1): work around slow reading child

    PR:     260938

    (cherry picked from commit c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee)

 usr.bin/script/script.c | 56 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 5 deletions(-)
Comment 5 commit-hook freebsd_committer freebsd_triage 2022-02-18 16:31:16 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=7e05fa3b449007adaa6e588ebb3b8d76f30b355c

commit 7e05fa3b449007adaa6e588ebb3b8d76f30b355c
Author:     наб <nabijaczleweli@nabijaczleweli.xyz>
AuthorDate: 2022-02-18 13:34:40 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2022-02-18 16:30:10 +0000

    uname: -v: strip final whitespace compatibly with uname(3)

    This restores POSIX.1 conformance

    PR: 260938

 usr.bin/uname/uname.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
Comment 6 commit-hook freebsd_committer freebsd_triage 2022-03-05 19:57:20 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=ed87197672b44f7f76b38e6450df2b4071c88a67

commit ed87197672b44f7f76b38e6450df2b4071c88a67
Author:     наб <nabijaczleweli@nabijaczleweli.xyz>
AuthorDate: 2022-02-18 13:34:40 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2022-03-05 19:56:11 +0000

    uname: -v: strip final whitespace compatibly with uname(3)

    This restores POSIX.1 conformance

    PR: 260938
    (cherry picked from commit 7e05fa3b449007adaa6e588ebb3b8d76f30b355c)

 usr.bin/uname/uname.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
Comment 7 Eugene Grosbein freebsd_committer freebsd_triage 2024-01-08 17:56:48 UTC
Fixed and merged to stable/13.