From nobody Mon Jan 10 15:35:38 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 414831957361; Mon, 10 Jan 2022 15:35:39 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JXdFQ6qmLz3rvt; Mon, 10 Jan 2022 15:35:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id CA06E27667; Mon, 10 Jan 2022 15:35:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 20AFZceT062126; Mon, 10 Jan 2022 15:35:38 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 20AFZc1M062125; Mon, 10 Jan 2022 15:35:38 GMT (envelope-from git) Date: Mon, 10 Jan 2022 15:35:38 GMT Message-Id: <202201101535.20AFZc1M062125@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: c0ba4c2ee2c4 - main - script(1): work around slow reading child List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1641828939; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=PGbNzDXFT1SHCGmfs9oedG5G+pIvNHBHIHMVJcPPO6s=; b=wZMvHKsTnMO3hb5jpbSY8zjikzAHY0+ltTVUKMetyrZ39F8gDk8lCUP8xxnhegQ9o5wtVu Zag0bdvnC+FxgQwuZvmYv4YyN8Infof/bF+kp5lu9Aj/QyA9i8oxPX/OcMNFmo9e/jRfmK Vbr3XNA9Vl4ltZZFb2SktiHJ/SeGd6Q0+ULD4fq8wVivWdDhuES03gfyk81QJXnNJ5f1Mz 80TPWK8Bfcvs8FwLy/EHwxbkMd6wPVfMmHBZFQcLBZDCFcXzCNhoCpL+80Dw+P+mqJJK26 owd8WUZJ+t+cqkehl2VK95T3T6qdpxNVWyKS0mMh9gtdPxw8jC9LAFfvFvRong== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1641828939; a=rsa-sha256; cv=none; b=QGWPyJGxpnNtwzgyJMsN/rxO2IvWK+2ZqwQgLCqOQw0bX+/46BJEFGzJVpVVAbNIH8mzDJ obX7bXqCVXhogbatcnXGtB4IUeCcL5TOOfn6zawMJv8gI1tEkwPLZWBlXlkFCGdfT9YBQY YWjfXFlYNBoVe9nZtqc4KxDO3zRJoB7t9eyl9ZZXSUojBtiJ7qpysH/TnN4/fEXLrmJRaY zq7O+cmigI3YSt7RuoUbIUfKhFNqqhPtzUwXgOLkxk/WK/jICWYsSdoikCBSrJY6egWhik 93zFxAD4rB6RQHFMJgpSUd0TuzgATtfrBA6dJIdo9+W7ue1eA/aH08vbVWflHw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee commit c0ba4c2ee2c48ec9892d10c0aca797f3685c53ee Author: Konstantin Belousov AuthorDate: 2022-01-08 13:19:14 +0000 Commit: Konstantin Belousov 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: наб 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(-) diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c index 4ecc2099926f..9c18dc73390f 100644 --- a/usr.bin/script/script.c +++ b/usr.bin/script/script.c @@ -45,6 +45,7 @@ static const char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93"; #include #include #include +#include #include #include #include @@ -70,6 +71,13 @@ struct stamp { uint32_t scr_direction; /* 'i', 'o', etc (also indicates endianness) */ }; +struct buf_elm { + TAILQ_ENTRY(buf_elm) link; + int rpos; + int len; + char ibuf[]; +}; + static FILE *fscript; static int master, slave; static int child; @@ -77,6 +85,7 @@ static const char *fname; static char *fmfname; static int fflg, qflg, ttyflg; static int usesleep, rawout, showexit; +static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list); static struct termios tt; @@ -98,8 +107,9 @@ main(int argc, char *argv[]) time_t tvec, start; char obuf[BUFSIZ]; char ibuf[BUFSIZ]; - fd_set rfd; - int aflg, Fflg, kflg, pflg, ch, k, n; + fd_set rfd, wfd; + struct buf_elm *be; + int aflg, Fflg, kflg, pflg, ch, k, n, fcm; int flushtime, readstdin; int fm_fd, fm_log; @@ -189,6 +199,12 @@ main(int argc, char *argv[]) err(1, "openpty"); ttyflg = 1; } + fcm = fcntl(master, F_GETFL); + if (fcm == -1) + err(1, "master F_GETFL"); + fcm |= O_NONBLOCK; + if (fcntl(master, F_SETFL, fcm) == -1) + err(1, "master F_SETFL"); if (rawout) record(fscript, NULL, 0, 's'); @@ -243,9 +259,12 @@ main(int argc, char *argv[]) readstdin = 1; for (;;) { FD_ZERO(&rfd); + FD_ZERO(&wfd); FD_SET(master, &rfd); if (readstdin) FD_SET(STDIN_FILENO, &rfd); + if (!TAILQ_EMPTY(&obuf_list)) + FD_SET(master, &wfd); if (!readstdin && ttyflg) { tv.tv_sec = 1; tv.tv_usec = 0; @@ -258,7 +277,7 @@ main(int argc, char *argv[]) } else { tvp = NULL; } - n = select(master + 1, &rfd, 0, 0, tvp); + n = select(master + 1, &rfd, &wfd, NULL, tvp); if (n < 0 && errno != EINTR) break; if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) { @@ -275,10 +294,37 @@ main(int argc, char *argv[]) if (cc > 0) { if (rawout) record(fscript, ibuf, cc, 'i'); - (void)write(master, ibuf, cc); + be = malloc(sizeof(*be) + cc); + be->rpos = 0; + be->len = cc; + memcpy(be->ibuf, ibuf, cc); + TAILQ_INSERT_TAIL(&obuf_list, be, link); + } + } + if (n > 0 && FD_ISSET(master, &wfd)) { + while ((be = TAILQ_FIRST(&obuf_list)) != NULL) { + cc = write(master, be->ibuf + be->rpos, + be->len); + if (cc == -1) { + if (errno == EWOULDBLOCK || + errno == EINTR) + break; + warn("write master"); + done(1); + } + if (cc == 0) + break; /* retry later ? */ if (kflg && tcgetattr(master, &stt) >= 0 && ((stt.c_lflag & ECHO) == 0)) { - (void)fwrite(ibuf, 1, cc, fscript); + (void)fwrite(be->ibuf + be->rpos, + 1, cc, fscript); + } + be->len -= cc; + if (be->len == 0) { + TAILQ_REMOVE(&obuf_list, be, link); + free(be); + } else { + be->rpos += cc; } } }