LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* POSSIBLE BUG: certain writes to pipe block (after select())
@ 2003-11-25 12:20 Ondrej Jombik
  2003-11-26  0:10 ` jw schultz
  0 siblings, 1 reply; 2+ messages in thread
From: Ondrej Jombik @ 2003-11-25 12:20 UTC (permalink / raw)
  To: linux-kernel

[ Please CC me in the answer as I am not in the list. ]

I discovered that certain writes to filedescriptor created with pipe()
system call will block even if select() previously returned change on
that filedescriptor -- of course select() returned change in "write"
fd_set.

While doing a deep investigation, I find out, that this write only
blocks if more than 4096 bytes are written. This is certain for 2.4.20,
2.4.21 and 2.6.0-test7 kernels. Other kernels were untested. What is
more interesting is the fact, that PIPE_BUF kernel constant (defined in
the file /usr/include/linux/limits.h) has value equal to 4096 bytes.

So when writting 4097 bytes write() blocks. When writting 4096 bytes it
does not. However I had never seen during my information hunt an
information, that only maximum PIPE_BUF bytes can be written into
filedescriptor created with pipe() system call. I think this is the
point of the whole thing, but I'm confused why this is not written
anywhere.

But anyway, I would like to mention, that expected behaviour is, that
write() will write 4096 bytes (so return value from write() syscall is
4096) and the rest should be up to user. So it has to be userspace deal
to wait for writing remaining byte(s).

Here is a simple demonstration program:

#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
#include <linux/limits.h>

#define TO_WRITE    (PIPE_BUF + 1) /* 4097 */

int main(void)
{
    int p[2];                 /* pipe */
    char to_write[TO_WRITE];  /* just memory-holder */
    fd_set wfds;              /* write fd_set */

    if (pipe(p) != 0)
        return 1;

    FD_ZERO(&wfds);
    FD_SET(p[1], &wfds);

    if (select(p[1] + 1, NULL, &wfds, NULL, NULL) > 0) {
        fprintf(stderr, "select() passed, can write to fd %d\n", p[1]);
        fprintf(stderr, "%d bytes written\n",
                write(p[1], to_write, TO_WRITE) /* this will block */
               );
    }

    return 0;
}


When you will strace this code, you will see how write() blocks:

pipe([4, 6])                            = 0
select(7, NULL, [6], NULL, NULL)        = 1 (out [6])
write(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4097

Changing the TO_WRITE constant from (PIPE_BUF + 1) to PIPE_BUF will make
write() in the example not to block.

Please let me know one important thing: if this is desirable behaviour
or it has to be considered as a bug.

[ Please CC me in the answer as I am not in the list. ]

--
  _/|   Ondrej Jombik - nepto@php.net - http://nepto.sk - ICQ #122428216
 <_  \  Platon SDG - open source software development - http://platon.sk
   `\|  UNIX is user friendly. It's selective about who its friends are!
    '`

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: POSSIBLE BUG: certain writes to pipe block (after select())
  2003-11-25 12:20 POSSIBLE BUG: certain writes to pipe block (after select()) Ondrej Jombik
@ 2003-11-26  0:10 ` jw schultz
  0 siblings, 0 replies; 2+ messages in thread
From: jw schultz @ 2003-11-26  0:10 UTC (permalink / raw)
  To: Ondrej Jombik; +Cc: linux-kernel

On Tue, Nov 25, 2003 at 01:20:18PM +0100, Ondrej Jombik wrote:
> [ Please CC me in the answer as I am not in the list. ]
> 
> I discovered that certain writes to filedescriptor created with pipe()
> system call will block even if select() previously returned change on
> that filedescriptor -- of course select() returned change in "write"
> fd_set.
> 
> While doing a deep investigation, I find out, that this write only
> blocks if more than 4096 bytes are written. This is certain for 2.4.20,
> 2.4.21 and 2.6.0-test7 kernels. Other kernels were untested. What is
> more interesting is the fact, that PIPE_BUF kernel constant (defined in
> the file /usr/include/linux/limits.h) has value equal to 4096 bytes.
> 
> So when writting 4097 bytes write() blocks. When writting 4096 bytes it
> does not. However I had never seen during my information hunt an
> information, that only maximum PIPE_BUF bytes can be written into
> filedescriptor created with pipe() system call. I think this is the
> point of the whole thing, but I'm confused why this is not written
> anywhere.
> 
> But anyway, I would like to mention, that expected behaviour is, that
> write() will write 4096 bytes (so return value from write() syscall is
> 4096) and the rest should be up to user. So it has to be userspace deal
> to wait for writing remaining byte(s).

This is correct behavior.  popen opens the file descriptors
with having default flags.  Therefore they have blocking
enabled.  See fcntl(2).

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-11-26  0:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-25 12:20 POSSIBLE BUG: certain writes to pipe block (after select()) Ondrej Jombik
2003-11-26  0:10 ` jw schultz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).