Quantcast
Viewing all articles
Browse latest Browse all 4928

Troubleshooting • C++ fgets behaving very oddly on Bookworm

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:

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...

Statistics: Posted by Peter Cyriax — Sun Feb 11, 2024 12:37 am



Viewing all articles
Browse latest Browse all 4928

Trending Articles