Messages in this thread Patch in this message | | | Date | Thu, 14 Oct 1999 08:34:21 +0200 | From | Natapov Gleb <> | Subject | [PATCH] /dev/random and nonblocking I/O bug |
| |
Hi. I've already posted this, but I haven't got any response.
It seems that read from /dev/random can block even if the device was opened with O_NONBLOCK flag.
I wrote the following program: ================================================================= #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h>
void main() { int randfd; char c; if( (randfd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0){ while(1){ if(read(randfd, &c, 1) != 1){ if( errno != EWOULDBLOCK && errno != 0 ) fprintf(stderr, "read error form random device"); break; } fprintf(stderr,"."); } } } ===================================================================== If you'll run this program when there are many bytes available in random pool you'll see that at some point program stops to print dots until some event, that adds data to random pool (mouse movement, keyboard stroke), will happen.
The problem is in random_read() (linux/drivers/char/random.c). The task puts itself in random_read_wait queue and change state to TASK_INTERRUPTIBLE.
If the random pool is empty and O_NONBLOCK is set it returns EAGAIN (as we are expecting) else it calls extract_entropy().
current->state == TASK_INTERRUPTIBLE at this point.
extract_entropy() fills the user's buffer with random data and if current->need_resched is not zero it calls resched(). The task goes to sleep in state TASK_INTERRUPTIBLE until somebody will write new random data into the pool and call wake_up_interruptible(&random_read_wait); It's exactly what we don't want - go to sleep while in nonblocking syscall.
The following patch solves this problem for me(2.2.10, 2.2.12): =================================================================== --- random.c.org Tue Oct 12 10:49:13 1999 +++ random.c Tue Oct 12 14:20:44 1999 @@ -1328,6 +1328,7 @@ schedule(); continue; } + current->state = TASK_RUNNING; n = extract_entropy(&random_state, buf, n, 1); if (n < 0) { retval = n; ==================================================================== But may be there is a better solution.
(I've looked at sources of 2.3.21 and, as far as I can see, it has the same problem).
Gleb.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |