From: Paul Marquis <pmarquis@iname.com>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: select() bug
Date: Thu, 02 Nov 2000 17:11:24 -0500 [thread overview]
Message-ID: <3A01E68C.EDA27165@iname.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 890 bytes --]
I've uncovered a bug in select() when checking if it's okay to write
on a pipe. It will report "false negatives" if there is any unread
data already on the pipe, even a single byte. As soon as the pipe
gets flushed, select() does the right thing.
Normally, I wouldn't think this such a big deal, except that Apache
uses the writability of s pipe to determine if any of its children
that are log file handlers are dead. If select() reports it can't
write immediately, Apache terminates and restarts the child process,
creating unnecessary load on the system.
The bug exists in the 2.2.x kernels up to and including 2.2.17 that
I've tried and I don't know it extends beyond pipes. I've attached
sample code to demonstrate the problem, which works correctly on BSD
and Solaris.
Is this a know bug?
--
Paul Marquis
pmarquis@iname.com
If it's tourist season, why can't we shoot them?
[-- Attachment #2: simple_pipe_test.c --]
[-- Type: application/octet-stream, Size: 2882 bytes --]
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char **argv)
{
int fd[2];
int i;
char buf[2];
fd_set write_fds;
struct timeval tv;
ssize_t n;
int status;
/* initialize */
buf[0] = 'h';
buf[1] = 'i';
do
{
/* create pipe */
if (0 > pipe(fd))
{
printf("pipe error - %s\n", strerror(errno));
break;
}
/*
* loop four times
* select for write, then write one byte
* after the second write, do a read
* odd selects succeed, even fail
*/
for (i = 0; i < 4; i++)
{
printf("iteration %d\n", i + 1);
status = 0;
/* do select */
FD_ZERO(&write_fds);
FD_SET(fd[1], &write_fds);
tv.tv_sec = 0;
tv.tv_usec = 0;
switch (select(fd[1] + 1, NULL, &write_fds, NULL, &tv))
{
case -1:
/* should probably check for EINTR and/or EWOULDBLOCK */
printf("select error - %s\n", strerror(errno));
break;
case 0:
/* no I/O */
puts("select returned 0 -- pipe not writable");
break;
default:
/* make sure our fd is writable */
if (FD_ISSET(fd[1], &write_fds))
{
puts("select says pipe is writable");
status = 1;
}
else
puts("select says pipe is not writable");
break;
}
/* do write */
n = write(fd[1], buf + (i % 2), 1);
switch (n)
{
case -1:
/* should probably check for EINTR and/or EWOULDBLOCK */
printf("write error - %s\n", strerror(errno));
break;
case 0:
/* no I/O */
puts("write returned 0 -- pipe closed");
break;
default:
printf("write succeeded - %d bytes written\n", n);
if (0 == status)
puts("select bug");
break;
}
/* do read */
if (0 == ((i + 1) % 2))
{
n = read(fd[0], buf, sizeof(buf));
switch (n)
{
case -1:
/* should probably check for EINTR and/or EWOULDBLOCK */
printf("write error - %s\n", strerror(errno));
break;
case 0:
/* no I/O */
puts("read returned 0 -- pipe closed");
break;
default:
printf("read succeeded - %d bytes read\n", n);
break;
}
}
}
}
while (0);
exit(0);
}
next reply other threads:[~2000-11-02 22:12 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2000-11-02 22:11 Paul Marquis [this message]
2000-11-02 22:27 ` select() bug Alan Cox
2000-11-02 22:42 ` Richard B. Johnson
2000-11-02 22:58 ` Paul Marquis
2000-11-03 0:53 ` Richard B. Johnson
2000-11-03 5:00 ` Paul Marquis
2000-11-03 13:05 ` Richard B. Johnson
2000-11-02 22:53 ` Paul Marquis
2000-11-02 22:58 ` Alan Cox
2000-11-02 23:08 ` Paul Marquis
2000-11-02 23:20 ` Alan Cox
2000-11-02 23:44 ` Paul Marquis
2000-11-02 23:53 ` H. Peter Anvin
2000-11-02 23:46 ` David S. Miller
2000-11-03 0:04 ` H. Peter Anvin
2000-11-02 23:52 ` David S. Miller
2000-11-03 0:13 ` H. Peter Anvin
2000-11-03 0:05 ` David S. Miller
2000-11-03 0:38 ` H. Peter Anvin
2000-11-03 0:01 ` Alan Cox
2000-11-02 23:55 ` Alan Cox
2000-11-03 5:52 ` dean gaudet
2000-11-03 7:05 ` Marc Lehmann
-- strict thread matches above, loose matches on Subject: below --
2000-11-05 16:14 Stanislav Meduna
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3A01E68C.EDA27165@iname.com \
--to=pmarquis@iname.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox