求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

软件和网站开发以及相关技术探讨
回复
qw4990
帖子: 10
注册时间: 2014-03-01 21:51
系统: ubuntu 13.10

求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

#1

帖子 qw4990 » 2014-04-12 13:21

程序的初步想法是想试一试阻塞信号,用信号 SIGALRM 来实验
我先是 signal(SIGALRM, alrmhandler);
然后设置一个定时器,每隔一段时间发送一个 SIGALRM 给程序,
接着在函数 alrmhandler 里面将SIGALRM阻塞,但是却出现了 EINTR 的错误,
请问下是怎么回事啊!

具体程序在下面

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

int cnt = 0;

void alrmblock(){
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGALRM);
errno = 4;
sigprocmask(SIG_BLOCK, &sigs, NULL);
printf("%s\n",strerror(errno));
}

void alrmhandler(int signum){
alrmblock();

cnt ++;
printf("%d\n",cnt);
}


int main(){
signal(SIGALRM, alrmhandler);

struct itimerval it;
it.it_value.tv_sec = 1;
it.it_interval.tv_sec = 1;
it.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &it , NULL);

while(1) pause();

return 0;
}
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

#2

帖子 astolia » 2014-04-12 19:14

你这里不是写了么
errno = 4;
.......
printf("%s\n",strerror(errno));
当然必然会输出Interrupted system call

如果把errno = 4删掉,会先输出一个Success,再是一连串的Interrupted system call,这是因为pause()就是这么干的

以下摘自man 2 pause

RETURN VALUE
pause() returns only when a signal was caught and the signal-catching
function returned. In this case pause() returns -1, and errno is set
to EINTR.
qw4990
帖子: 10
注册时间: 2014-03-01 21:51
系统: ubuntu 13.10

Re: 求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

#3

帖子 qw4990 » 2014-04-13 1:50

astolia 写了:你这里不是写了么
errno = 4;
.......
printf("%s\n",strerror(errno));
当然必然会输出Interrupted system call

如果把errno = 4删掉,会先输出一个Success,再是一连串的Interrupted system call,这是因为pause()就是这么干的

以下摘自man 2 pause

RETURN VALUE
pause() returns only when a signal was caught and the signal-catching
function returned. In this case pause() returns -1, and errno is set
to EINTR.

那个erron = 4;是我调试的时候忘记删除了。。。
我这里主要是有这么一个问题
就是第一次接受alrm信号过后,进入alrmhandler,然后在alrmblock中已经把alrm信号屏蔽了才对啊
既然屏蔽了 那么为什么第二次信号来的时候 , 还能进入alrmhandler函数内呢?
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

#4

帖子 astolia » 2014-04-13 11:57

信号阻塞机制和你理解的有点不一样。在handler里设置的sigprocmask只对此次处理有效,不会影响到正常流程和下次handler的处理。而且,handler默认会阻塞当前收到的信号,所以说你在handler中再次设置阻塞是没有用的

代码: 全选

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <pthread.h> 

int cnt = 0;

void alrmblock(){
	sigset_t sigs;
	sigemptyset(&sigs);
	sigaddset(&sigs, SIGALRM);
	sigaddset(&sigs, SIGTERM);
	sigprocmask(SIG_BLOCK, &sigs, NULL);
	printf("%s\n",strerror(errno));
}

void alrmhandler(int signum){
	sigset_t sigs;
	sigprocmask(0, NULL, &sigs);
	printf("old SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("old SIGTERM: %d\n", sigismember(&sigs, SIGTERM));

	alrmblock();

	sigprocmask(0, NULL, &sigs);
	printf("new SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("new SIGTERM: %d\n", sigismember(&sigs, SIGTERM));

	cnt ++;
	printf("%d\n",cnt);
}


int main(){
	signal(SIGALRM, alrmhandler);

	sigset_t sigs;
	sigprocmask(0, NULL, &sigs);
	printf("main SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("main SIGTERM: %d\n", sigismember(&sigs, SIGTERM));
	raise(SIGALRM);

	sigprocmask(0, NULL, &sigs);
	printf("main SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("main SIGTERM: %d\n", sigismember(&sigs, SIGTERM));
	raise(SIGALRM);

	return 0;
}
qw4990
帖子: 10
注册时间: 2014-03-01 21:51
系统: ubuntu 13.10

Re: 求大牛帮忙看一下为什么我这个程序出现了 Interrupted system call 的错误啊

#5

帖子 qw4990 » 2014-04-13 21:58

astolia 写了:信号阻塞机制和你理解的有点不一样。在handler里设置的sigprocmask只对此次处理有效,不会影响到正常流程和下次handler的处理。而且,handler默认会阻塞当前收到的信号,所以说你在handler中再次设置阻塞是没有用的

代码: 全选

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <pthread.h> 

int cnt = 0;

void alrmblock(){
	sigset_t sigs;
	sigemptyset(&sigs);
	sigaddset(&sigs, SIGALRM);
	sigaddset(&sigs, SIGTERM);
	sigprocmask(SIG_BLOCK, &sigs, NULL);
	printf("%s\n",strerror(errno));
}

void alrmhandler(int signum){
	sigset_t sigs;
	sigprocmask(0, NULL, &sigs);
	printf("old SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("old SIGTERM: %d\n", sigismember(&sigs, SIGTERM));

	alrmblock();

	sigprocmask(0, NULL, &sigs);
	printf("new SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("new SIGTERM: %d\n", sigismember(&sigs, SIGTERM));

	cnt ++;
	printf("%d\n",cnt);
}


int main(){
	signal(SIGALRM, alrmhandler);

	sigset_t sigs;
	sigprocmask(0, NULL, &sigs);
	printf("main SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("main SIGTERM: %d\n", sigismember(&sigs, SIGTERM));
	raise(SIGALRM);

	sigprocmask(0, NULL, &sigs);
	printf("main SIGALRM: %d\n", sigismember(&sigs, SIGALRM));
	printf("main SIGTERM: %d\n", sigismember(&sigs, SIGTERM));
	raise(SIGALRM);

	return 0;
}
知道怎么回事了 非常感谢啊!!

不过觉得pause的工作方式有点奇特。。
回复