tags:

views:

283

answers:

4

I would like to stuff an 'A' character back into stdin using ungetc on receipt of SIGUSR1. Imagine that I have a good reason for doing this.

When calling foo(), the blocking read in stdin is not interrupted by the ungetc call on receipt of the signal. While I didn't expect this to work as is, I wonder if there is a way to achieve this - does anyone have suggestions?

void handler (int sig)
{
  ungetc ('A', stdin);
}

void foo ()
{
  signal (SIGUSR1, handler);

  while ((key = fgetc (stdin)) != EOF)
  {
    ...
  }
}
+1  A: 

It is not entirely clear what your goal is, but is this what you are looking for?

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

int handle = 0;

void handler (int sig) {
  handle = 1;
}

void foo () {
  int key;

  signal (SIGUSR1, handler);

  while ((key = fgetc (stdin)) != EOF) {
    printf("%c\n",key);
    if (handle) {
      handle = 0;
      ungetc('A',stdin);
    }
  }
}

int main(void) {
  printf("PID: %d\n",getpid());
  foo();
}

It produces this output:

PID: 8902
test (typed on stdin)
t
A
e
s
t
Jamie
Not quite - I'm looking for a way to get that 'A' ahead of the 't'.
Paul Beckingham
+1  A: 

FILE*s are not async safe.

You cannot operate on a FILE* in a signal handler while someone else also uses that same FILE*. functions you can all in a signal handler is stated here:

http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html . (It might be different on a windows machine, but still any FILE* are not safe there either.

nos
+1  A: 

This is essentially the same as @Jamie's answer, slightly changed to support your desire to process the A before the t, but it's too hard to type code into a comment box, so I've posted this answer separately.

int insert_an_A = 0;
void handler(int sig) { insert_an_A = 1; }

void process_char(char c) { ... }

int main(int argc, char **argv) {
    int c;
    /* skip signal setup */
    while ((c = fgetc(stdin)) != EOF) {
        if (insert_an_A) {
            process_char('A');
            insert_an_A = 0;
        }
        process_char(c);
    }
}

If you want to process an handler received during the call to fgetc that returns EOF, you should also check insert_an_A after exiting the while loop.

Note also that in general the best practice for signal handlers is to set a global variable and return from the handler. Elsewhere in your program, look for that variable changing and react appropriately.

Dale Hagglund
+3  A: 
jschmier