免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: jeanlove
打印 上一主题 下一主题

[C] fcntl加文件锁什么时候会被信号中断? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-07 19:38 |显示全部楼层 |倒序浏览
10可用积分
[本问题已解决]
经过timespace的提醒,使用sigaction替代signal来注册SIGARLM,使得fcntl被信号中断以后得以重启(SA_RESTART),代码如下
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
extern int errno;
extern "C" void s(int sig,siginfo_t *, void *){
printf("signal handle: %d\n",sig);
}
int main(void){
int fdes=open("kg",O_RDWR|O_CREAT,0664);
if(fdes<0){
  printf("open fail\n");
  exit(1);
}
struct sigaction act,oact;
sigemptyset(&act.sa_mask);
act.sa_sigaction=s;
act.sa_flags=SA_RESTART;
sigaction(SIGALRM,&act,&oact);
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence=SEEK_SET;
lock.l_len=0;
alarm(5);
if(fcntl(fdes,F_SETLKW,&lock)==-1){
  alarm(0);
  printf("error=%d,%s\n",errno,strerror(errno));
  close(fdes);
  exit(1);
}
printf("lock got\n");
signal(SIGALRM,SIG_IGN);
sleep(60);
close(fdes);
return 0;
}

现在两个进程能同时运行,不会出现system call interrupted了! 分送出!

-------------------------------------------------------------------------
在一台Solaris的工作站遇到一个问题
int fdes = open(path,O_RDWR|O_CREAT,0664);
if(fcntl(fdes,F_SETLKW,&lock)  == -1){
printf("%d text: %s\n",lerrno,strerror(lerrno));
}
...
...

这段程序遇到了错误,打印:
4 text: Interrupted system call
我查了一下手册:
F_SETLKW:行为如同F_SETLK,除了不能获取锁时会睡眠等待外。如果在等待的过程中接收到信号,会立即返回并将errno置为EINTR

我把问题提取出来了,形成一个小程序:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<signal.h>
extern int errno;
extern "C" void s(int sig){
printf("signal handle: %d\n",sig);
}
int main(void){
int fdes=open("kg",O_RDWR|O_CREAT,0664);
if(fdes<0){
  printf("open fail\n");
  exit(1);
}
signal(SIGALRM,&s);
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence=SEEK_SET;
lock.l_len=0;
alarm(5);
if(fcntl(fdes,F_SETLKW,&lock)==-1){
  signal(SIGALRM,SIG_IGN);
  alarm(0);
  printf("error=%d,%s\n",errno,strerror(errno));
  close(fdes);
  exit(1);
}
printf("lock got\n");
signal(SIGALRM,SIG_IGN);
sleep(20);
close(fdes);
return 0;
}
(1)编译运行:
一个term里面./a.out (称为进程a)
另一个term里面也瞬间./a.out (称为进程b)

(2)运行结果:
a进程运行以后对文件加锁,打印"lock got",然后睡20s,结束
b进程启动以后fcntl会等待(因为F_SETLKW),然后第5s的时候,进程接受到了SIGALRM,(因为alarm(5)的原因,然后打印
signal handle: 14
error=4,Interrupted system call

(3)问题是:
a进程为什么没有执行信号处理函数s从而打印出"signal handle: 14"
b进程的信号处理函数已经起了作用,为什么fcntl(fdes,F_SETLKW,&lock)仍然被信号中断?

测试环境: solaris8+CC
谢谢!!!!!
请问: fcntl加文件锁,什么时候会接收到信号呢? 每次运行到这里都失败。

谢谢!!!!!!

[ 本帖最后由 jeanlove 于 2009-4-8 17:11 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-04-08 13:52 |显示全部楼层
原帖由 astezheng 于 2009-4-7 19:41 发表
其他参数我没有看到,但是如果你这个是一个获取锁的操作,而锁拿不到的话,就睡眠了,然后在睡眠的时候被你的信号打断了

你可以查一下你的程序里面哪儿有很频繁的发信号操作


有了一点进展,我把问题提取出来了,形成一个小程序,1楼的帖子贴出来了。

[ 本帖最后由 jeanlove 于 2009-4-8 14:24 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-04-08 15:20 |显示全部楼层
原帖由 timespace 于 2009-4-8 14:59 发表

signal(SIGALRM,SIG_IGN);
sleep(20);
你在sleep之前都忽略了SIGALRM,所以a不会执行s


信号处理函数生效,系统调用也能被信号中断,至于系统调用是否会重启,取决于实现,也就是说看文档。


只要满 ...

补充一点:

我把原程序中的alarm()和signal(SIGALRM)去掉了,换成了signal(SIGHUP),然后我在a,b两个进程运行的时候:
>kill -HUP <b的pid>

同样,b进程打印
signal handle: 14
error=4,Interrupted system call

并退出。也就是说在solaris8这个环境上面,fcntl会被所有的signal中断。
为什么呢?

论坛徽章:
0
4 [报告]
发表于 2009-04-08 17:18 |显示全部楼层
问题已解决,更新请看1楼的最新程序
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP