considering this code:
#include<cstdio>
extern"C"{
#include<termios.h>
#include<unistd.h>
}
int main(){
termios termattr_bak;
termios termattr;
/* switch to raw mode*/
tcgetattr(STDIN_FILENO,&termattr_bak);
termattr.c_iflag |= IGNBRK;
termattr.c_iflag &= ~unsigned(INLCR|ICRNL|IXON|IXOFF);
termattr.c_lflag &= ~unsigned(ICANON|ECHO|ECHOK|ECHOE|ECHONL|ISIG|IEXTEN);
termattr.c_cc[VMIN] = 1;
termattr.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO,TCSAFLUSH,&termattr);
/* */
printf("test\r\n");
printf("test\r\n");
printf("test\r\n");
fflush(stdout);
/* restore terminal attributes*/
tcsetattr(STDIN_FILENO,TCSAFLUSH,&termattr_bak);
return 0;
}
the program compiles with g++ main.cc and works just as expected around 80% of the time with this trace:
test
test
test
but sometimes, randomly, the trace is like this:
test
test
test
or this:
test
test
test
or even those above with capital letters (!?) like
TEST
TEST
TEST
and so on.
I just run the same program again and again in the same terminal with randomly the different behaviors above. It is the same under both gnome-terminal and xterm.
I tried to fflush and/or tcflush and/or tcdrain at different locations with no success.
What is happening here and how do I prevent this ?
EDIT:
It seems that gcc -Og main.cc produces a different code that works correctly. So it looks to me like something is beeing broken by the optimisations, which means I am doing something wrong with the code which only shows up when optimized (but What ?), or less likely there is a bug with GCC
EDIT2:
As SergeBallesta mentionned, I was not initializing the termios structure before use, which was leading the random problems above. This one works :
#include<cstdio>
extern"C"{
#include<termios.h>
#include<unistd.h>
}
int main(){
termios termattr_bak;
termios termattr{};//<<<<<<<<<<<<<<< zero-init the struct
/* switch to raw mode*/
tcgetattr(STDIN_FILENO,&termattr_bak);
termattr.c_iflag |= IGNBRK;
termattr.c_iflag &= ~unsigned(INLCR|ICRNL|IXON|IXOFF);
termattr.c_lflag &= ~unsigned(ICANON|ECHO|ECHOK|ECHOE|ECHONL|ISIG|IEXTEN);
termattr.c_cc[VMIN] = 1;
termattr.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO,TCSAFLUSH,&termattr);
/* */
printf("test\r\n");
printf("test\r\n");
printf("test\r\n");
fflush(stdout);
/* restore terminal attributes*/
tcsetattr(STDIN_FILENO,TCSAFLUSH,&termattr_bak);
return 0;
}
You should not be zero-initializing the termios structure. Get the current settings, make a copy, then adjust it for raw mode using
cfmakeraw().