Re: SMP-ix86-threads-fork: Linux 2.4.x kernel problem identified [phantom read()]

From: Kaz Kylheku (kaz@ashi.footprints.net)
Date: Mon Sep 10 2001 - 11:42:08 EST


On Mon, 10 Sep 2001, Wolfram Gloger wrote:

> On a variety of dual-ix86-SMP systems running Linux-2.4.[0-10pre]
> kernels (compiled with gcc-2.95.2 and gcc-2.95.4) it eventually
> happens that a read(fd, buf, sz) system call returns successfully but
> it _actually hasn't read any bytes into buf_ (maybe the bytes go
> somewhere else but I haven't determined where).

Wow, that is nuts! :)

> --- linuxthreads/manager.c.orig Mon Jul 23 19:54:13 2001
> +++ linuxthreads/manager.c Mon Sep 10 11:48:49 2001
> @@ -150,8 +150,18 @@
> }
> /* Read and execute request */
> if (n == 1 && (ufd.revents & POLLIN)) {
> - n = __libc_read(reqfd, (char *)&request, sizeof(request));
> - ASSERT(n == sizeof(request));
> + int sz_read;
> + request.req_kind = 0x123456;
> + for (sz_read=0; sz_read<sizeof(request); sz_read+=n) {
> + n = __libc_read(reqfd, (char *)&request + sz_read,
> + sizeof(request) - sz_read);
> + if (n < 0)
> + continue;
> + }

Careful; when you continue, the increment expression sz_read += n
is still evaluated.

And please note that sz_read < sizeof(request) is a signed-unsigned
comparison!

So if sz_read is negative, its value will be converted to a positive
value of type size_t, and your loop may terminate prematurely.

So it's perfectly possible to observe the behavior you are seeing
if __libc_read() returns -1. Because then sz_read will acquire the
value -1, and the guard expresssion sz_read < sizeof(request) will yield
zero, terminating the loop.

Could you recode the test patch to eliminate these suspicions and re-test?

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 15 2001 - 21:00:27 EST