Skip to content

Commit

Permalink
pty04: Retry reads when short and wait longer
Browse files Browse the repository at this point in the history
Even though reads are blocking and packets are flipped into the netdevice
buffer whole, it seems read may return before a full packet is read into user
land. Retrying read should prevent timeouts and read failures on some
machines.

Also this increases the timeout to wait for the checkpoint to a large value
because sometimes the kernel stalls, possibly while trying to (re)claim
memory, and this causes the checkpoint wait to timeout and everything to be
cleaned up. If the kernel is left in a stalled state, this can result in a
stack trace which is more useful.

Closes: #674

Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
Reported-by: Jan Stancek <jstancek@redhat.com>
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Acked-by: Jan Stancek <jstancek@redhat.com>
Cc: Petr Vorel <pvorel@suse.cz>
  • Loading branch information
Richard Palethorpe authored and pevik committed May 14, 2020
1 parent 9bc1bd4 commit 035336b
Showing 1 changed file with 27 additions and 7 deletions.
34 changes: 27 additions & 7 deletions testcases/kernel/pty/pty04.c
Expand Up @@ -177,7 +177,7 @@ static void write_pty(const struct ldisc_info *ldisc)
TST_RETVAL_NOTNULL);
if (ret < 0)
tst_brk(TBROK | TERRNO, "Failed 1st write to PTY");
tst_res(TPASS, "Wrote PTY 1");
tst_res(TPASS, "Wrote PTY %s %d (1)", ldisc->name, ptmx);

written = 0;
ret = TST_RETRY_FUNC(try_write(ptmx, data, len, &written),
Expand All @@ -188,7 +188,7 @@ static void write_pty(const struct ldisc_info *ldisc)
if (tcflush(ptmx, TCIFLUSH))
tst_brk(TBROK | TERRNO, "tcflush(ptmx, TCIFLUSH)");

tst_res(TPASS, "Wrote PTY 2");
tst_res(TPASS, "Wrote PTY %s %d (2)", ldisc->name, ptmx);

while (try_write(ptmx, data, len, NULL) >= 0)
;
Expand Down Expand Up @@ -288,6 +288,24 @@ static void check_data(const struct ldisc_info *ldisc,
tst_res(TINFO, "Will continue test without data checking");
}

static void try_read(int fd, char *data, ssize_t size)
{
ssize_t ret, n = 0;
int retry = mtu;

while (retry--) {
ret = read(fd, data, size - n);

if (ret < 0)
break;

if ((n += ret) >= size)
return;
}

tst_brk(TBROK | TERRNO, "Read %zd of %zd bytes", n, size);
}

static void read_netdev(const struct ldisc_info *ldisc)
{
int rlen, plen = 0;
Expand All @@ -305,20 +323,21 @@ static void read_netdev(const struct ldisc_info *ldisc)

tst_res(TINFO, "Reading from socket %d", sk);

SAFE_READ(1, sk, data, plen);
try_read(sk, data, plen);
check_data(ldisc, data, plen);
tst_res(TPASS, "Read netdev 1");
tst_res(TPASS, "Read netdev %s %d (1)", ldisc->name, sk);

SAFE_READ(1, sk, data, plen);
try_read(sk, data, plen);
check_data(ldisc, data, plen);
tst_res(TPASS, "Read netdev 2");
tst_res(TPASS, "Read netdev %s %d (2)", ldisc->name, sk);

TST_CHECKPOINT_WAKE(0);
while ((rlen = read(sk, data, plen)) > 0)
check_data(ldisc, data, rlen);

tst_res(TPASS, "Reading data from netdev interrupted by hangup");

close(sk);
tst_free_all();
}

Expand All @@ -342,7 +361,7 @@ static void do_test(unsigned int n)
}

if (!SAFE_FORK()) {
TST_CHECKPOINT_WAIT(0);
TST_CHECKPOINT_WAIT2(0, 100000);
SAFE_IOCTL(pts, TIOCVHANGUP);
tst_res(TINFO, "Sent hangup ioctl to PTS");
SAFE_IOCTL(ptmx, TIOCVHANGUP);
Expand All @@ -357,6 +376,7 @@ static void cleanup(void)
{
ioctl(pts, TIOCVHANGUP);
ioctl(ptmx, TIOCVHANGUP);
close(sk);

tst_reap_children();
}
Expand Down

0 comments on commit 035336b

Please sign in to comment.