again: if ((n = read(fd, buf, BUFSIZE)) < 0) { if (errno == EINTR) goto again; /* just an interrupted system call */ /* handle other errors */ }
#include <stdio.h> #include <setjmp.h> #include <unistd.h> #include <signal.h> static jmp_buf env_alarm; static void sig_alarm(int signo) { longjmp(env_alarm, 1); } int main(int argc, char* argv[]) { char buf[4096]; if (signal(SIGALRM, sig_alarm) == SIG_ERR) { fprintf(stderr, "signal(SIGALRM) error\n"); } if (setjmp(env_alarm) != 0) { fprintf(stderr, "read timeout\n"); return -1; } alarm(5); int nread = 0; if ((nread = read(STDIN_FILENO, buf, 4096)) < 0) { fprintf(stderr, "read error\n"); } alarm(0); write(STDOUT_FILENO, buf, nread); return 0; }
struct sigaction { void (*sa_handler)(int); /* addr of signal handler */ sigset_t sa_mask; /* addtional signals to block */ int sa_flags; /* signal options */ void (*sa_sigaction)(int, siginfo_t *, void *); /* alternate handler */ };
posix使用sigaction實現signal(原有的signal函數語義不可靠)網絡
typedef void Sigfunc(int); Sigfunc* signal(int signo, Sigfunc* func) { struct sigaction newact, oldact; newact.sa_handler = func; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; if (signo == SIGALRM) { #ifdef SA_INTERRUPT newact.sa_flags |= SA_INTERRUPT; #endif } else { #ifdef SA_RESTART newact.sa_flags |= SA_RESTART; #endif } if (sigaction(signo, &newact, &oldact) < 0) { return (SIG_ERR); } return oldact.sa_handler; }