• O_RDWR On Named Pipes

    From Lawrence D'Oliveiro@21:1/5 to All on Sat Mar 15 21:52:16 2025
    Typically when you open a file descriptor on a pipe, it’s either for
    reading or writing, but not both.

    However, when you open a named pipe, it is possible to specify the
    mode O_RDWR; but does this work, or return an error? And if it doesn’t
    return an error, what exactly does it do?

    I checked some relevant man pages
    <https://manpages.debian.org/fifo(7)>
    <https://manpages.debian.org/pipe(7)>, but they completely avoid any
    mention of O_RDWR mode.

    So I tried it. And it works without error. You get back a single file descriptor, that you can use for both writing to the pipe and reading
    from it. So if no other processes open the same named pipe, you can
    write something to it (I suppose until the kernel buffer fills up),
    and read the same thing back again.

    Not very useful, on the face of it. But I guess it means you can (with appropriate coordination from both ends) switch the direction of data
    flow at any point, without having to close and reopen the named pipe.
    Basically O_RDWR gives you a half-duplex communication channel, where
    O_RDONLY and O_WRONLY will give you the ends of a simplex
    (unidirectional) channel.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to All on Mon Mar 17 16:14:56 2025
    On 17.03.2025 15:22, hymie! wrote:
    In our last episode, the evil Dr. Lacto had captured our hero,
    Lawrence D'Oliveiro <ldo@nz.invalid>, who said:
    Typically when you open a file descriptor on a pipe, it’s either for
    reading or writing, but not both.

    However, when you open a named pipe, it is possible to specify the
    mode O_RDWR; but does this work, or return an error? And if it doesn’t
    return an error, what exactly does it do?

    I'm not exactly sure what you're asking here, but I just set this up yesterday.

    I think the OP is not wondering about the usefulness of the pipe
    communication spread between client and server processes. But it
    rather gets more interesting if both directions are used by the
    same process. As in, say, this code fragment

    for (int i=0; i<=200000; i++)
    {
    sprintf(buf, " A %05d", i%10000);
    if (write(myfifo, buf, 8) < 8) {
    fprintf (stderr, "*** write A failed at i=%d\n", i);
    exit (1);
    }
    sprintf(buf, " B %05d", i%10000);
    if (write(myfifo, buf, 8) < 8) {
    fprintf (stderr, "*** write B failed at i=%d\n", i);
    exit (1);
    }
    if (read(myfifo, buf, 8) < 8) {
    fprintf (stderr, "*** read failed at i=%d\n", i);
    exit (2);
    }
    buf[8] = '\0';
    printf ("%s\n", buf);
    }

    This will overflow the FIFO at some point - twice as much data
    is written than read/processed. But there may be interesting
    applications where some initial huge data in the pipe will get
    processed, rewritten in a reduced form, and over time solved
    the task (when iterated reduction is complete). - While this
    would be (still) not convincing (since you could operate as
    well just on a buffer as opposed to a FIFO) it might get more
    interesting in case of co-operating processes.

    Short answer; I thing it makes sense to not restrict the FIFO
    interface unnecessarily.

    Janis


    I open a FIFO

    char myfifoname[100];
    int myfifo;
    sprintf(myfifoname,"/tmp/program.%08d",getpid());
    mkfifo(myfifoname, S_IRUSR | S_IWUSR);
    myfifo = open(myfifoname,O_RDWR | O_NONBLOCK);

    Then I spawn a bunch of forks which already have the FIFO open. The
    forked children write to the FIFO

    if ( (cpid[9]=fork()) == 0)
    {
    for (;;)
    {
    write(myfifo,"9a\n",strlen("9a\n"));
    napms( (int) Random(50,250));
    write(myfifo,"9b\n",strlen("9b\n"));
    napms( (int) Random(50,250));
    }
    }

    And the parent process reads from the FIFO

    for (;;)
    {
    int r=read(myfifo,buf,10);
    int window = buf[0]-'0';
    if (buf[1] == 'a')
    /* Do stuff on the provided window */
    if (buf[1] == 'b')
    /* Do stuff on the provided window */
    }

    In my case, I know there's always a single-digit number followed by a
    single character.

    --hymie! http://nasalinux.net/~hymie hymie@nasalinux.net


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From hymie!@21:1/5 to who on Mon Mar 17 14:22:30 2025
    In our last episode, the evil Dr. Lacto had captured our hero,
    Lawrence D'Oliveiro <ldo@nz.invalid>, who said:
    Typically when you open a file descriptor on a pipe, it’s either for reading or writing, but not both.

    However, when you open a named pipe, it is possible to specify the
    mode O_RDWR; but does this work, or return an error? And if it doesn’t return an error, what exactly does it do?

    I'm not exactly sure what you're asking here, but I just set this up
    yesterday.

    I open a FIFO

    char myfifoname[100];
    int myfifo;
    sprintf(myfifoname,"/tmp/program.%08d",getpid());
    mkfifo(myfifoname, S_IRUSR | S_IWUSR);
    myfifo = open(myfifoname,O_RDWR | O_NONBLOCK);

    Then I spawn a bunch of forks which already have the FIFO open. The
    forked children write to the FIFO

    if ( (cpid[9]=fork()) == 0)
    {
    for (;;)
    {
    write(myfifo,"9a\n",strlen("9a\n"));
    napms( (int) Random(50,250));
    write(myfifo,"9b\n",strlen("9b\n"));
    napms( (int) Random(50,250));
    }
    }

    And the parent process reads from the FIFO

    for (;;)
    {
    int r=read(myfifo,buf,10);
    int window = buf[0]-'0';
    if (buf[1] == 'a')
    /* Do stuff on the provided window */
    if (buf[1] == 'b')
    /* Do stuff on the provided window */
    }

    In my case, I know there's always a single-digit number followed by a
    single character.

    --hymie! http://nasalinux.net/~hymie hymie@nasalinux.net

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)