使用signal註冊訊號,有可能不會使阻塞通訊端被訊號打斷,請看如下代碼:
/** * Try to reproduce this issue: * Set an alarm before connect() of blocking socket, connect() won't be * interrupted when this alarm is fired. * gcc -o signal signal.c */#include <signal.h>#include <unistd.h>#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netinet/in.h>#include <errno.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>voidsig_handler(int sig){ printf("in signal handler\n");}die(const char *fmt, ...){ char buf[1024] = {0}; va_list va; va_start(va, fmt); vsnprintf(buf, sizeof(buf), fmt, va); va_end(va); fprintf(stderr, "%s\n", buf); exit(1); /* stdlib.h */}intmain(int argc, char **argv){#ifdef USE_SIGACTION struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; if(sigaction(SIGALRM, &sa, NULL) < 0) die("sigaction failed");#else if(SIG_ERR == signal(SIGALRM, sig_handler)) { die("signal failed\n"); }#endif int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in to; memset(&to, 0, sizeof(to)); to.sin_family = AF_INET; if(!inet_aton("192.168.1.254", &to.sin_addr)) { die("convert failed"); } to.sin_port = htons(22322); alarm(2); if(connect(sock, (struct sockaddr*)&to, sizeof(to)) < 0 && errno == EINTR) { close(sock); die("connect() is interrupted"); } return 0;}
不定義宏USE_SIGACTION,使用signal註冊訊號,connect()永遠不會被打斷。
但是使用sigaction註冊訊號,能夠使connect函數被訊號打斷:
$gcc -o signal signal.c -DUSE_SIGACTION$./signal in signal handlerconnect() is interrupted
我的環境:
$gcc --versiongcc (GCC) 4.4.2 20091027 (Red Hat 4.4.2-7)$uname -r2.6.31.5-127.fc12.i686.PAE
結論:盡量使用sigaction註冊訊號。
網上這方面的資料很少,參考SO一個文章:
http://stackoverflow.com/questions/3582226/recv-is-not-interrupted-by-a-signal-in-multithreaded-environment