Search code examples
cprocessncurses

ncurses library prints weird characters on key pressed


I have a thread that catches a key pressed through getch and if the key pressed is arrowUp or arrowDown then it scrolls my terminal using ncurses functions (incrementing an integer variable used to show elements from a linked list). This works fine most of the times but sometimes (usually when i hold an arrow pressed) ncurses prints on terminal weird and unexpected characters like 9;32H (it seems like an uncatched input). Does anyone know how i can solve this?

issue screenshot

Here an MCVE

#include <ncurses.h>
#include <stdlib.h>
#include <pthread.h> 

#define MAX(a,b) ((a) > (b) ? (a) : (b))

void * listener(void* p){
    int* shift = (int*) p;
    int ch;
    while (1)
    {
        ch = getch();
        if(ch == KEY_UP){
            *shift = MAX(0, *shift - 1);
        }
        else if(ch == KEY_DOWN){
            *shift = *shift + 1;
        }
    }
}
 
int main(){
    char* c = malloc(100);

    for(int i = 0; i < 100; i++){
        c[i] = 'A' + (random() % 26);
    }

    int shift = 0;

    pthread_t th;

    initscr();
    raw();
    noecho();
    keypad(stdscr, TRUE);
    start_color();
    curs_set(0);

    pthread_create(&th, NULL, listener, (void*) &shift);

    while(1){
        for(int j = shift; j < shift+stdscr->_maxy; ++j){
            move(j-shift,0);
            clrtoeol();
            mvaddch(j-shift, 0, c[j]);
            refresh();
        }
    }

    endwin();   
    free(c);
    return 0;
}

This snippet shows my issue if you hold arrow down

EDIT: The issue seems to be related to getch() from different thread that modifies global variables of ncurses library. Does anyone know a thread-safe way to get a char input?


Solution

  • I actually solved my issue using getchar instead of getch since it seems not to be thread safe. I found out that getch modifies ncurses global variable and calls refresh() at the end, so if another thread is changing ncurses stuff (e.g. cursor position) your program may have an unexpected behavior (in my case printing escape characters representing set cursor position)