ncurses and multiprocessing

60 views Asked by At

I'm experiencing a problem with getch()(ncurses library). I need to continuosly print an "object" (a child process that sends data to the parent through a pipe; the child is the one that calls the blocking getch() and the parent is the one that receives the data and prints it to the screen), controlled by the user, on the terminal, but since the parent is the one occupied with writing and refreshing the window the getch() which comes with the associated refresh is causing the window to spawn gibberish. This is a school project so I can't change the library nor the fundamental structure (I need to employ multiprocessing and a child process needs to listen to the input stream) but I could change the function that gets the input data. There is also an option to get the input from an external process and send it to the control process through a local socket but even in that case the refresh would still be a danger to my window's coherence.There is also to add the fact that I don't completely understand the problem and I'm not 100% whether or not it is really a choerence issue.

I tried to change the getch() to non-blocking. I tried using halfdelay and timeout. The results were the same. I think something that could work would be to generate a second window used only for listening but I don't think it would be acceptable. I can't use neither semaphores nor mutexes and it seems that there isn't a refresh-less getch() option.

An example of what I mean:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/time.h> 

int pipe_fds[2];
struct msg {
    int id;   
    int x;   
    int y;    
};
void moving_object();
int main() {

   initscr(); noecho(); curs_set(0); nodelay(stdscr, 1); keypad(stdscr, 1); cbreak();
   int flag = 0; int flag1 = 0; pid_t pid1;
   if (pipe(pipe_fds) == -1) {
        perror("Pipe call");
        exit(1);
    }
     while(1) {
     
        if (flag == 0) {
      
          pid1 = fork();
          if (pid1 < 0) {perror("fork call"); _exit(2);}
          if (pid1 == 0) {
             close(pipe_fds[0]);
             while(1);
             _exit(2);
             }
          else {
             flag = 1;
             }
          
          }
          if (flag1 == 0) {
               pid1 = fork();
           if (pid1 < 0) {perror("fork call"); _exit(2);}
           if (pid1 == 0) {
               close(pipe_fds[0]);
               moving_object();
             }
           else {
               flag1 = 1;
              } }
              
           mvprintw(5, 5, "GIBBERISH");
           refresh();
        
     
     
     
     }
     wait(NULL); wait(NULL);
  }
  
  
void moving_object() {
    int c;
    struct msg m1;
    pid_t pid;

    m1.id = 1;

    while (1) {
        c = (int)getch();
        switch (c) {
            case KEY_UP:
                m1.x = 0;
                m1.y = -2;
                break;
            case KEY_DOWN:
                m1.x = 0;
                m1.y = 2;
                break;
            case KEY_LEFT:
                m1.x = -2;
                m1.y = 0;
                break;
            case KEY_RIGHT:
                m1.x = 2;
                m1.y = 0;
                break;
        }
        if (c != ERR) {
            //write(pipe_fds[1], &m1, sizeof(m1));
        }
    }
}

The pipes are only there to highlight my use-case. The problem can be seen if you run the program: there is no "GIBBERISH" printed. The weird thing is that it works not only if you comment out getch and/or set flag1 to 1. "GIBBERISH" is printed even if you set flag to 1; which I just can't understand.

0

There are 0 answers