关于linux线程实时信号的一个问题
2007-07-02 09:18
411 查看
关于linux线程实时信号的一个问题
最近在项目的迁移方面发现linux线程的一个问题 感觉很奇怪,在2.4内核运行正常的程序在高版本linux上运行出现实时信号错误,Real-Time 0.原来是,在启动network线程的时候,用的事信号驱动I/O。在这个线程启动的时候,会把SIGRTMIN和SIGIO, 信号block,然后在 wait 这信号,如果条件满足会向自己发一个SIGRTMIN信号,sigqueue(getpid(),SIGRTMIN,sigval).问题就出在getpid()上,原来在rh8的内核上,每个线程都有一个pid,和进程的pid不一样。所以用这个语句发送的信号在rh8上事正常work的 。
但是到了高版本的linux,一个进程的所有线程gepid()都是唯一的。这时候用这个语句发送 信号等于是向进程发信号,但是进程的信号掩码没有把这个信号block,所以整个程序会推出。
下面是一个测试代码,在centos和rh8 run,结果完全不一样。
#include<errno.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
enum {MYSELF, FromMain};
void TimerTick(int time)
{
printf("TimerTick,send a signal to pid=%d/n",getpid());
union sigval svNew;
svNew.sival_int = MYSELF;
sigqueue(getpid(), SIGRTMIN, svNew);
};
void * pthread_routine(void * arg)
{
sigset_t m_Sigset;
sigemptyset(&m_Sigset);
sigaddset(&m_Sigset, SIGRTMIN);
sigprocmask(SIG_BLOCK, &m_Sigset, NULL);
printf("I am routine ,pid=",getpid());
printf("waiting for%d/n",SIGRTMIN);
signal(SIGALRM, TimerTick);
struct itimerval itvInterval;
itvInterval.it_value.tv_sec = 1;
itvInterval.it_value.tv_usec = 100;
itvInterval.it_interval.tv_sec = 1;
itvInterval.it_interval.tv_usec = 60 * 1000;
setitimer(ITIMER_REAL, &itvInterval, NULL);
while(1){
siginfo_t siginfo;
int sigRet;
sigRet = sigwaitinfo(&m_Sigset, &siginfo);
//printf("Got a signal %d/n",sigRet);
if (sigRet == -1 || sigRet == SIGIO) {
if (sigRet == -1 && errno == EINTR)
continue;
else {
printf("Error/n");
}
}
if(siginfo.si_value.sival_int==MYSELF)
{
printf("Got a signal from myself,the signum is %d/n",sigRet);
}else if(siginfo.si_value.sival_int==FromMain)
{
printf("Got a signal from main thread ,the signu is %d/n",sigRet);
}
else{
printf("Got a signal from unkown/n");
}
}
return NULL;
};
int main()
{
sigset_t mainset;
sigset_t testset;
sigemptyset(&testset);
printf("I am main pid=/n",getpid());
pthread_t thread_id;
size_t stack_size;
pthread_create(&thread_id,NULL,pthread_routine,NULL);
printf("selep some time in main thread/n");
sleep(5);
sigprocmask(SIG_BLOCK, &testset, &mainset);
if(sigismember(&mainset,SIGRTMIN))
{
printf("the SIGRTMIN is in the mainset,it's set by other thread/n");
}
else{
printf("the SIGRTMIN is no the mainset/n");
}
sigprocmask(SIG_BLOCK,&mainset,NULL);
printf("the pid is %d/n",getpid());
union sigval svNew;
svNew.sival_int = FromMain;
sigqueue(getpid(), SIGRTMIN, svNew);
pthread_join(thread_id,NULL);
return 0;
}
最近在项目的迁移方面发现linux线程的一个问题 感觉很奇怪,在2.4内核运行正常的程序在高版本linux上运行出现实时信号错误,Real-Time 0.原来是,在启动network线程的时候,用的事信号驱动I/O。在这个线程启动的时候,会把SIGRTMIN和SIGIO, 信号block,然后在 wait 这信号,如果条件满足会向自己发一个SIGRTMIN信号,sigqueue(getpid(),SIGRTMIN,sigval).问题就出在getpid()上,原来在rh8的内核上,每个线程都有一个pid,和进程的pid不一样。所以用这个语句发送的信号在rh8上事正常work的 。
但是到了高版本的linux,一个进程的所有线程gepid()都是唯一的。这时候用这个语句发送 信号等于是向进程发信号,但是进程的信号掩码没有把这个信号block,所以整个程序会推出。
下面是一个测试代码,在centos和rh8 run,结果完全不一样。
#include<errno.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
enum {MYSELF, FromMain};
void TimerTick(int time)
{
printf("TimerTick,send a signal to pid=%d/n",getpid());
union sigval svNew;
svNew.sival_int = MYSELF;
sigqueue(getpid(), SIGRTMIN, svNew);
};
void * pthread_routine(void * arg)
{
sigset_t m_Sigset;
sigemptyset(&m_Sigset);
sigaddset(&m_Sigset, SIGRTMIN);
sigprocmask(SIG_BLOCK, &m_Sigset, NULL);
printf("I am routine ,pid=",getpid());
printf("waiting for%d/n",SIGRTMIN);
signal(SIGALRM, TimerTick);
struct itimerval itvInterval;
itvInterval.it_value.tv_sec = 1;
itvInterval.it_value.tv_usec = 100;
itvInterval.it_interval.tv_sec = 1;
itvInterval.it_interval.tv_usec = 60 * 1000;
setitimer(ITIMER_REAL, &itvInterval, NULL);
while(1){
siginfo_t siginfo;
int sigRet;
sigRet = sigwaitinfo(&m_Sigset, &siginfo);
//printf("Got a signal %d/n",sigRet);
if (sigRet == -1 || sigRet == SIGIO) {
if (sigRet == -1 && errno == EINTR)
continue;
else {
printf("Error/n");
}
}
if(siginfo.si_value.sival_int==MYSELF)
{
printf("Got a signal from myself,the signum is %d/n",sigRet);
}else if(siginfo.si_value.sival_int==FromMain)
{
printf("Got a signal from main thread ,the signu is %d/n",sigRet);
}
else{
printf("Got a signal from unkown/n");
}
}
return NULL;
};
int main()
{
sigset_t mainset;
sigset_t testset;
sigemptyset(&testset);
printf("I am main pid=/n",getpid());
pthread_t thread_id;
size_t stack_size;
pthread_create(&thread_id,NULL,pthread_routine,NULL);
printf("selep some time in main thread/n");
sleep(5);
sigprocmask(SIG_BLOCK, &testset, &mainset);
if(sigismember(&mainset,SIGRTMIN))
{
printf("the SIGRTMIN is in the mainset,it's set by other thread/n");
}
else{
printf("the SIGRTMIN is no the mainset/n");
}
sigprocmask(SIG_BLOCK,&mainset,NULL);
printf("the pid is %d/n",getpid());
union sigval svNew;
svNew.sival_int = FromMain;
sigqueue(getpid(), SIGRTMIN, svNew);
pthread_join(thread_id,NULL);
return 0;
}
相关文章推荐
- Linux 信号处理,是否同一个线程组的线程收到SIGSEGV其它线程都会被挂起
- 请使劲回答一个关于UNIX/Linux自己主动扩展stack的问题
- 【Linux开发技术之常见问题】一个建立线程时常见的问题:invalid conversion from `void*' to `void*(*)(void*)
- 解决Linux下多个进程或线程同时对一个文件进行写操作问题
- 关于信号槽连接地方的一点心得,一个问题困扰了一下午才解决,纪念一下。
- 【Linux开发技术之常见问题】一个建立线程时常见的问题:invalid conversion from `void*' to `void*(*)(void*)
- 关于异步、线程、委托的一个问题
- 关于Java组播在Linux中的一个问题
- linux下关于进程、线程及信号编程的所有头文件说简要明
- 关于前一个问题在linux中的试验
- Linux 2. 关于pthread_cond_signal 唤醒两个线程的问题
- linux 实时线程优先级问题——数值越大优先级越高吗?
- 请使劲回答一个关于UNIX/Linux自动扩展stack的问题
- 【Linux开发技术之常见问题】一个建立线程时常见的问题:invalid conversion from `void*' to `void*(*)(void*)
- 一个关于linux进程函数kill的问题
- 请使劲回答一个关于UNIX/Linux自动扩展stack的问题
- 面试中关于Linux的信号常问的问题
- 关于多个异步任务线程如何取消上一个线程的问题
- Linux中关于权限的一个问题
- Linux访问Windows共享文件夹,关于mount cifs的一个问题