0

Consider this signal handler for SIGINT:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>

static sigjmp_buf env_buffer;

void sig_handler(int signo) {
  if (signo == SIGINT) {
      //fseek( stdout, 0, SEEK_END );
      //fflush(stdout);
      printf( "Interrupted by user!\n" );
      siglongjmp( env_buffer, signo );
  }
}

int main(void) {

    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = sig_handler;
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        printf("sigaction failed\n");
        exit(1);
    }

    int val = sigsetjmp( env_buffer, 1 );
    if ( val != 0 ) {
        printf( "exit main()..\n" );
        return 1;
    }
    for( int i=0; ; i++ ) {
        printf( "%d\n", i % 10);
    }
    return 0;
}

Output:

[...]
0
1
2
3
4
5
6
7
8
9 
0 
1
2
3
4
^C5
Interrupted by user!
exit main()..

Question:

  • Why is there an integer written after ^C (here: 5)? It appears that this number is a random number between 0 and 9.
  • Is it possible to get rid of this number?

I think I have to erase the stdout buffer somehow. It seems this cannot be done with fseek or fflush.

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • 2
    Note that strictly, under POSIX rules, you [should not use `printf()` in signal handlers](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler/). Standard C is far more restrictive; you can do very, very little in a signal handler in standard C. None of which is to say that people don't do what you're doing and get away with it most of the time. – Jonathan Leffler Apr 08 '17 at 17:19
  • 1
    Similarly, POSIX and C lay down rules for how you can use the value returned by [`sigsetjmp()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsetjmp.html) — you need to refer to [`setjmp()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setjmp.html) too — and being the RHS of an assignment expression isn't one of the legitimate contexts. Again, you may well get away with it, but the standards don't guarantee that you will. – Jonathan Leffler Apr 08 '17 at 17:22
  • Thanks for the comments. Note that if I remove `printf` from the signal handler the spurious output is still there, so it seems it is not related to using `printf` inside the signal handler? – Håkon Hægland Apr 08 '17 at 17:27
  • My best guess is that the `^C` comes from your terminal settings (`stty echoctl`), and the `5` was in the `printf()` buffer before the interrupt was hit, so it appeared as would be expected. I'm not certain about how the terminal driver handles the 'echoctl', but it won't involve going through the standard I/O streams (it will work with file descriptors, not streams). – Jonathan Leffler Apr 08 '17 at 17:30
  • Yes it seems it is related to terminal's internal buffer. I tried to redirect output to a file and there is no spurious output in the file. It only appears when printing to the terminal. – Håkon Hægland Apr 08 '17 at 17:43
  • error messages should be displayed on `stderr`, not `stdout`. when the error is from a system function, then the text indicating why the OS thinks the error occurred, should also be output. For application generated errors, use: `fprintf( stderr, ... );` for system generated errors use: `perror( ... );` – user3629249 Apr 09 '17 at 13:47

0 Answers0