Fix spurious kassert on interrupted blocking read from /dev/random.
Return EINTR in this case instead. While here, clarify comment. Fixes PR kern/48119, simpler than the patch attached there, per discussion with tls@, who had this right in the earlier version of rndpseudo.c before I broke it (oops!).
This commit is contained in:
parent
72b022939e
commit
db4eba3c26
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rndpseudo.c,v 1.16 2013/07/21 22:30:19 riastradh Exp $ */
|
||||
/* $NetBSD: rndpseudo.c,v 1.17 2013/09/25 03:14:55 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.16 2013/07/21 22:30:19 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.17 2013/09/25 03:14:55 riastradh Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_compat_netbsd.h"
|
||||
|
@ -389,18 +389,32 @@ rnd_read(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
|
|||
goto out;
|
||||
|
||||
/*
|
||||
* Do at most one iteration for /dev/random and return
|
||||
* a short read without hanging further. Hanging
|
||||
* breaks applications worse than short reads. Reads
|
||||
* can't be zero unless nonblocking from /dev/random;
|
||||
* in that case, ask caller to retry, instead of just
|
||||
* returning zero bytes, which means EOF.
|
||||
* For /dev/urandom: Reads always succeed in full, no
|
||||
* matter how many iterations that takes. (XXX But
|
||||
* this means the computation can't be interrupted,
|
||||
* wihch seems suboptimal.)
|
||||
*
|
||||
* For /dev/random, nonblocking: Reads succeed with as
|
||||
* many bytes as a single request can return without
|
||||
* blocking, or fail with EAGAIN if a request would
|
||||
* block. (There is no sense in trying multiple
|
||||
* requests because if the first one didn't fill the
|
||||
* buffer, the second one would almost certainly
|
||||
* block.)
|
||||
*
|
||||
* For /dev/random, blocking: Reads succeed with as
|
||||
* many bytes as a single request -- which may block --
|
||||
* can return if uninterrupted, or fail with EINTR if
|
||||
* the request is interrupted.
|
||||
*/
|
||||
KASSERT((0 < n_read) || (ctx->rc_hard &&
|
||||
ISSET(fp->f_flag, FNONBLOCK)));
|
||||
KASSERT((0 < n_read) || ctx->rc_hard);
|
||||
if (ctx->rc_hard) {
|
||||
if (n_read == 0)
|
||||
if (0 < n_read)
|
||||
error = 0;
|
||||
else if (ISSET(fp->f_flag, FNONBLOCK))
|
||||
error = EAGAIN;
|
||||
else
|
||||
error = EINTR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue