Here's the problem: this program should receive input from stdin and count the bytes inserted; the SIGUSR1 signal whill stop the main program and will print on file standard error how many bytes have been copied when I send the SIGUSR1.
That's how my teacher wants me to do this: in one terminal type
cat /dev/zero | ./cpinout | cat >/dev/null
while from a second terminal send signals with
kill -USR1 xxxx
where xxxx is the pid of cpinout.
I updated my previous code:
/* cpinout.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#define BUF_SIZE 1024
volatile sig_atomic_t countbyte = 0;
volatile sig_atomic_t sigcount = 0;
/* my_handler: gestore di signal */
static void sighandler(int signum) {
if(sigcount != 0)
fprintf(stderr, "Interrupted after %d byte.\n", sigcount);
sigcount = contabyte;
}
int main(void) {
int c;
char buffer[BUF_SIZE];
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = sighandler;
if(sigaction(SIGUSR1, &action, NULL) == -1) {
fprintf(stderr, "sigusr: sigaction\n");
exit(1);
}
while( c=getc(stdin) != EOF ) {
countbyte++;
fputc(c, stdout);
}
return(0);
}
Signals may only write
volatile sig_atomic_t
variables according to the C89 and POSIX 7 standards:Implementations often offer more, but I doubt that using non-volatile global variables or printf is something provided by yours.
EDIT
In the comments you mentioned that you are running the command as:
cat /dev/zero | ./namefile | cat >/dev/null
The behaviour is actually fine.
/dev/zero
is an endless stream of zeros, which are being sent to the program. So it's counting them up very quickly. When you interrupt, it stops and you're left with a large number.The problem may be related to the fact that the signal handler may be called while the global variable is being updated (if this takes more than one instruction). However, the GNU documentation states that it's safe to assume that an
int
is always atomic on a POSIX system.The only other possibility I can think of is that you're calling
fputc
in the loop, withprintf
in the handler (it should however be safe to callprintf
in a handler if it's not being called by the program). Try removingfputc
from the loop to see if it resolves the problem.EDIT:
This appears to explain the problem. This relates to the kind of functions that are safe to call from within a signal handler:
Your program is interrupting a stdio function, which seems to fit this perfectly.
Here's an alternative approach: