Search code examples
cpthreadsstdineof

How to programmatically stop reading from stdin?


fgetc() and other input functions can return when there's no data on the file descriptor. This can be simulated for console applications reading from stdin typing Ctrl-D on keyboard (at least on unix). But how to do it programmatically? For example, how to return from the fgetc() in the reader thread in the following code (NB: ignore the possible race condition)?

#include <pthread.h>
#include <stdio.h>

void* reader()
{
    char read_char;
    while((read_char = fgetc(stdin)) != EOF) {
        ;
    }

    pthread_exit(NULL);
}

int main(void)
{
    pthread_t thread;
    pthread_create(&thread, NULL, reader, NULL);

    // Do something so the fgetc in the reader thread will return

    pthread_exit(NULL);
}

Thanks!


Solution

  • It seems you want a threads to stop blocking on fgetc(stdin) when some event occurs to handle that event instead. If that's the case you could select() on both stdin and some other message pipe so that the thread can handle input from both:

    fd_set descriptor_set
    FD_ZERO(&descriptor_set); 
    FD_SET(STDIN_FILENO, &descriptor_set); 
    FD_SET(pipefd, &descriptor_set); 
    
    if (select(FD_SETSIZE, &descriptor_set, NULL, NULL, NULL) < 0) 
    { 
      // select() error
    } 
    
    if (FD_ISSET(STDIN_FILENO, &descriptor_set)) {
      // read byte from stdin
      read(STDIN_FILENO, &c, 1);
    }
    
    if (FD_ISSET(pipefd, &descriptor_set)) 
      // Special event. Do something else
    

    Also note that only one thread in your process should be reading from stdin.