bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Blocking behaviour of write after select


From: Max Neunhoeffer
Subject: Blocking behaviour of write after select
Date: Mon, 13 Nov 2006 18:23:45 +0100
User-agent: Mutt/1.5.6+20040907i

Hello!

Using glibc 2.3.2 on an i386 intel Linux system I observe that "write"
after a call to "select" that returns that a file descriptor belonging
to the writing end of a pipe is writable does not behave as it should,
at least with my understanding of the documentation. Namely, if I write
larger amounts of data using "write" it blocks until all data can be
written.

However, I understand that the documentation of "select" under "Waiting
for Input or Output" in the C-library info document explicitly promises
that if "select" indicates a file descriptor to be "writable", then the
next call to "write" will not block. It may actually write fewer than
the requested number of bytes and report so, but it must not block.

I understand that this promise also holds if the file descriptor is in
"blocking" mode (option O_NONBLOCK) not set. If I explicitly set this
flag, things work like I would expect them.

The problem is illustrated by the little program below, called with
a number greater than about 4096 (the limit seems to differ between
machines!). One can clearly see that the call to "write" blocks even
after a successful "select".

Is this intended behaviour? If so, I believe the documentation must be
improved. If not, is it a Linux-specific problem? Where is the bug?

Thanks in advance for comments,
  Max.


#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <sys/select.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stddef.h>
#include <fcntl.h>

char buf[10000000];

int main(int argc, char *argv[])
{
    int fd[2];
    int pid;
    int len;
    int i;
    fd_set fdset;

    len = atoi(argv[1]);

    pipe(fd);  /* we assume it worked! */

#ifdef WITHNONBLOCK
    fcntl(fd[1],F_SETFL,O_NONBLOCK);
#endif

    pid = fork();   /* we assume it worked! */
    if (pid == 0) {   /* the child */
        i = read(fd[0],buf,1024);
        printf("Child: read %d bytes\n",i);
        sleep(5);
        i = read(fd[0],buf,len);
        printf("Child: read %d bytes\n",i);
        exit(0);
    }

    /* The parent: */

    i = write(fd[1],buf,1024);   /* This should work */
    printf("Parent: wrote %d bytes\n",i);
    FD_ZERO(&fdset);
    FD_SET(fd[1],&fdset);
    i = select(fd[1]+1,NULL,&fdset,NULL,NULL);
    printf("Parent: select found %d writable file descriptors\n",i);
    if (i < 1 || !(FD_ISSET(fd[1],&fdset))) {
        printf("Parent: alert, fd not ready but select returned!\n");
        exit(0);
    }
    i = write(fd[1],buf,len);
    printf("Parent: wrote %i bytes\n",i);
    close(fd[1]);
    close(fd[0]);
    printf("Parent: closed pipe\n");
    exit(0);
}
-- 
   # #   Max Neunhoeffer <address@hidden>
  #####  Gerlachstrasse 20-22, 52064 Aachen, Germany (private)
   # #   Lehrstuhl D fuer Mathematik, RWTH, Templergraben 64, 52062 Aachen
  #####  Tel.: +49 241 406605 (private) / +49 241 8094550 (institute)
   # #   May the Source be with you!





reply via email to

[Prev in Thread] Current Thread [Next in Thread]