1

This is the interested portion of my code (semplified because it's a bit of a mess): archive.c:

int main(int argc, char* argv[])
{
    pthread_t* thread_tid;
    pthread_create(&thread_tid, NULL, wthread_boss_body, NULL);
    xpthread_join(tid_sig_handler, NULL, QUI);  
    return 0;
}

void* wthread_boss_body(void* v)
{
    dati* tdati = (dati*)v;
    int fd = open("caposc",O_RDONLY);
    if(fd<0) error handling...

    while(true)
    {
        char test[7];
        puts("provo a leggere...\n");
        read(fd, test, 7);
        printf("ecco qua: %s", test);
        sleep(1);
    }
    pthread_exit(NULL);
}

server.py:

FIFOcaposc = 'caposc'
def main():
    try:
        os.mkfifo(FIFOcaposc)
    except FileExistsError:
        pass
    except OSError as e:
        print(f"Creazione FIFO {FIFOcaposc} fallita: {e}")
        exit(1) 
    
    
    try:
        caposc = open(FIFOcaposc, 'w')
        print("caposc aperta\n")
    except OSError as e:
        print(f"Apertura FIFO {FIFOcaposc} fallita: {e}")
        exit(1)

    while(True):
        print("writing...\n")
        print(f"{caposc.write('abcdefg')}\n")
        time.sleep(1)
    

    caposc.close()
    capolet.close()
    os.unlink(FIFOcaposc)
    os.unlink(FIFOcapolet)

main()

running both, server.py keep cycling forever and writing on the fifo (the write return always 7) as expected, but archive.c remain stuck at the read at the first cycle and never returns. For what i understood, the read don't return until something is available to be read on the fifo. But since it seems there actually is something to read, my mind is blown.

i made another stupid couple of programs, i made this and this works fine: test.c:

void* thread_body(void* v);

int main(int argc, char* argv[])
{
    pthread_t t1;
    
    pthread_create(&t1, NULL, &thread_body, NULL);
    
    pthread_join(t1, NULL);
}


void* thread_body(void* v)
{
    int fd = open("pipeprova", O_RDONLY);
    
    char stringa[8];
    while(true)
    {
        int e = read(fd, &stringa, 7);
        if(e == 0) puts("no");
    
        stringa[7] = '\0';
        printf("%s\n", stringa);
    }
    pthread_exit(NULL);
}

testpy.py:

try:
    os.mkfifo("pipeprova")
except FileExistsError:
    pass
except OSError as e: # TODO: verifica che OSError non comprenda FileExistsError
    print(f"Creazione FIFO fallita: {e}")
    exit(1)
try:
    fifo = open("pipeprova", 'w')
    print("aperta\n")
except OSError as e:
    print(f"Apertura FIFO fallita: {e}")
    exit(1)
while(True):
    print(f"{fifo.write('abcdefg')}\n")
fifo.close();

I really don't get whats wrong, after a long research i found something that make my code works, with this while in my server.py it works:

while(True):
    caposc = open(FIFOcaposc, 'w')
    print("writing...\n")
    print(f"{caposc.write('abcdefg')}\n")
    time.sleep(1)
    caposc.close()

Do i really need to make the open and close syscalls everytime? Why? is there a more efficient way?

Borbi
  • 25
  • 5
  • 1
    You write seven characters to the pipe, and read seven characters. But those seven characters does not contain the string null-terminator character `'\0'` that is required for the string to be called a string in C. That means when you print its contents with `%s` you will have *undefined behavior*. The second C program which you claim work *do* properly null-terminate the string. – Some programmer dude Jul 01 '23 at 13:09
  • Hi @Someprogrammerdude, i edited my code and addet the '\0' before printing, thank you. But i have the same problem, the thread of archive.c get stuck at the first read which never returns. Unless i open and close the fifo every time i write something. – Borbi Jul 01 '23 at 13:31
  • 1
    Perhaps it is just a cut -n-paste error, but if you elide the comment `/* error handling */` it seems that your code logic is "if open fails, then enter the read loop" – William Pursell Jul 01 '23 at 15:43

1 Answers1

3

By default, file I/O in Python is buffered. This means nothing will be actually written to the FIFO until you either flush or close the stream, or overflow the internal buffer.

To overcome this, either disable buffering (and use binary mode, and convert the string to bytes upon writing):

caposc = open(FIFOcaposc, 'wb', buffering=0)
...
print(f"{caposc.write('abcdefg'.encode())}\n")

or flush the buffer every now and then

print(f"{caposc.write('abcdefg')}\n")
caposc.flush()
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Man you're right i disabled the buffer and it works. Thank you very much you saved me bro! – Borbi Jul 03 '23 at 16:51