'Communication through named pipe works with file descriptors but not with unbuffered operation to FILE*

I have two programs that need to communicate with each other. I choose named pipe as IPC mechanism. One program is in C++ and the other one is a python script but for testing purposes, I will show the behaviours with two C programs.

Let's say program A is the C++ one and program B is the python script. I have two named pipes: one for A to B communications and one for B to A communications. I need the pipes to be unbuffered because I will use the read operation as a synchronization mechanism and I want to be able to send 1 byte of data, plus no text will be transmitted between the programs, only raw bytes.

Program A:

  1. creates the named pipes in unbuffered mode and fork and launch the python script (i.e. Program B)
  2. read from pipe to program B
  3. write to pipe for program B

Program B:

  1. write to pipe for program A
  2. read from pipe to program A

In program A I use the functions fopen,fwrite and fread for IO operations. In python, I used the open (not os.open) function.

My problem is that at step 2 of program B I have a BUS ERROR on program A at step 3, plus in program A the data read at step 2 is not the data send from step 1 of program B.

Here is a diagram of what happened:

enter image description here

To understand what happened, I created to small C programs that I launched manually to reproduce the error:

equivalent to program A:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main(void)
{
    umask(0);
    mkfifo(".ed.fifo", 0777);
    mkfifo(".de.fifo", 0777);
    FILE* toDebugger = fopen(".ed.fifo", "wb");
    FILE* fromDebugger = fopen(".de.fifo", "rb");
    setbuf(toDebugger, "U");
    setbuf(fromDebugger, "U");

    uint8_t g;

    fread(&g,1,1,fromDebugger);
    printf("received %#x\n",g);

    g = 0xAB;
    fwrite(&g,1,1,toDebugger);

    fclose(toDebugger);
    fclose(fromDebugger);

    return EXIT_SUCCESS;
}

equivalent to program B:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main (void)
{
    FILE* fromEmulator = fopen(".ed.fifo", "rb");
    FILE* toEmulator = fopen(".de.fifo", "wb");
    setbuf(fromEmulator, "U");
    setbuf(toEmulator, "U");

    uint8_t g = 5;
    fwrite(&g,1,1,toEmulator);
    fread(&g,1,1,fromEmulator);
    printf("received from c++: %#x\n", g);

    fclose(toEmulator);
    fclose(fromEmulator);

    return EXIT_SUCCESS;
}

In those two test programs, I tried to use file descriptors instead of FILE* with the functions open, read and write and everything worked perfectly:

equivalent to program A:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main(void)
{
    umask(0);
    mkfifo(".ed.fifo", 0777);
    mkfifo(".de.fifo", 0777);
    int toDebugger = open(".ed.fifo", O_WRONLY);
    int fromDebugger = open(".de.fifo", O_RDONLY);

    uint8_t g;
    
    read(fromDebugger,&g,1);
    printf("received %#x\n",g);

    g = 0xAB;
    write(toDebugger,&g,1);

    close(toDebugger);
    close(fromDebugger);

    return EXIT_SUCCESS;
}

equivalent to program B:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main (void)
{
    int fromEmulator = open(".ed.fifo", O_RDONLY);
    int toEmulator = open(".de.fifo", O_WRONLY);

    uint8_t g = 5;
    write(toEmulator,&g,1);
    read(fromEmulator,&g,1);
    printf("received from c++: %#x\n", g);

    close(toEmulator);
    close(fromEmulator);

    return EXIT_SUCCESS;
}

My question is why using directly file descriptors makes things suddenly work as expected, and since in my real application program B is in python, is using file descriptors in python possible and portable on windows?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source