Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4917

Troubleshooting • Re: C++ fgets behaving very oddly on Bookworm

$
0
0
Hi,

I could really use some help here.

I have a C++ progrm that uses fgets to read messages (commands) out of a fifo. These commands tell the C++ program to do things with the GPIO pins (and potentially other hardware interfaces).

I'm no expert in C++, so it's possible I have done something wrong, but it does look to me as if there is a bug in the C++ implementation of fgets, at least under Bookworm on a Pi 5. I will be testing other environments, but that takes time.

There seem to be two bugs:

1.
On the first call to fgets it apparently works correctly, waiting untill there is data in the pipe, reading it upto and including the first \n character,, and flushing what it has read from the fifo. But thereafter it no longer waits for data to be present, but returns immediately from each call with rubbish in the input buffer (always 6 characters long) but no error on the read, maxing out one CPU core in a tight loop.

I think the correct behaviour is called "blocking mode). If so, the issue is that a sucessful call to fgets sets the mode to not_blocking

I have managed to fix this by opening the fifo (fopen) immediately before the call to fgets, and closing it (fclose) immediately after the fgets call returns. So it's only ever on the "first call" to fgets, which works. But this is clearly a bodge.

2.
On further testing it appears that even the first call to fgets is not quite working correctly. I does not flush what it has read from the fifo: instad it flushes the entire contents of the fifo. Normally you would not notice the difference as the commands are quite short and you typically put them into the fifo one at a time, so what fgets normall reads IS the entire fifo contents; but in general (and during testing) it should only flush what it has read (as I understand it.


This is part of a larger program: I'm in the process of cutting it down to check that this is not a side effect of something apparently unrealated. I'm also going to run it on Bullseye on a Pi 4 to check the behaviour is the same.

Once I've got this down to something managable I'll post the code , but the guts of it is:

Code:

      std::stringstream msgsst;          // stringstream to accumulate the input message      char bufl;                                       // last character in current fgets read buffer      do{                                                 // loop til you get a \n            char msgbuf[msglen];          // fgets read buffer            int len;                                     // number of characters read            fd = fopen(fifoname, "r");     // open the fifo            fgets(msgbuf, msglen, fd);  //read til \n, buffer full or EOF            fclose(fd);                               // close the fifo            len = strlen(msgbuf);            // find number of characters read            bufl = msgbuf[len-1];             // find the last character            msgsst << msgbuf;               // build up to complete input stringstream                         } while (bufl != '\n');                   // keep going til you have a \n
Which looks pretty unexceptional to me...
I guess the program sending the commands closes the FIFO at the other end and after that the receiver returns an error with the rubbish. Opening the FIFO again causes the receiver to wait until the sender opens the other end and sends another message, but then the sender closes it and subsequent reads again fail. In conclusion either the receiver has to keep opening the FIFO or the sender has to stop closing it.

Maybe you want a local socket instead.

Statistics: Posted by ejolson — Sun Feb 11, 2024 2:34 am



Viewing all articles
Browse latest Browse all 4917

Trending Articles