Username: Password:

Linux下多线程编程和信号处理易疏忽的一个例子
来源:互连网作者:互连网 发布时间:2008-04-07 03:06:10

这几天把一个网络流量采集器程式基本改好了,原来在main函数中把几个子线程启动后就睡10分钟后开始清理子线程后退出。现在想改成子线程启动后主线程进入无限睡眠,直到收到SIGTERM或SIGINT。主程式如下:
其他头文档
#include //信号处理所需要的头文档
int main(int argc, char * argv[]){
  //其他所需要的变量声明  
  sigset_t sig_set,sig_pending;


  // 配置信号阻塞
  sigemptyset(&sig_set);
  sigaddset(&sig_set,SIGTERM);
  sigaddset(&sig_set,SIGINT);
  sigprocmask(SIG_BLOCK,&sig_set,NULL);


  启动几个子线程  
  ...........

  // 配置信号阻塞
  sigemptyset(&sig_set);
  sigaddset(&sig_set,SIGTERM);
  sigaddset(&sig_set,SIGINT);
  sigprocmask(SIG_BLOCK,&sig_set,NULL);
 
  //主线程进入睡眠,等待信号到达后跳出睡眠  
  while(1){
          sigpending(&sig_pending);
          if(sigismember(&sig_pending, SIGTERM)||
                    sigismember(&sig_pending,SIGINT)){
                break;
          }
          sleep(2);
  }

  //子线程退出情理
  ................
  return 0;

}

程式运行后发现 当按下Ctrl+C后程式没有出现子线程退出时的信息而是立即退出,很奇怪。
仔细分析了一下,发现问题在于忽略了Linux下的多线程模型的特点。

Linux 下的线程实质上是轻量级进程(light weighted process),线程生成时会生成对应的进程控制结构,只是该结构和父线程的进程控制结构共享了同一个进程内存空间。同时新线程的进程控制结构将从父线程(进程)处复制得到同样的进程信息,如打开文档列表和信号阻塞掩码等。由于我们是在子线程生成之后修改了信号阻塞掩码,此刻子线程使用的是主线程原有的进程信息,因此子线程仍然会对SIGINT和SIGTERM信号进行反应,因此当我们用Ctrl+C发出了 SIGINT信号的时候,主进程不处理该信号,而子进程(线程)会进行默认处理,即退出。子进程退出的同时会向父进程(线程)发送SIGCHLD信号,表示子进程退出,由于该信号没有被阻塞,因此会导致主进程(线程)也立即退出,出现了前述的运行情况。因而该问题的一个解决方法是在子线程生成前进行信号配置, 或在子线程内部进行信号配置。由于子线程是往往是个事务处理函数,因此我建议在简单的情况下采用前者,假如需要处理的信号比较复杂,那就必须使用后一种方法来处理。这样,以上的程式逻辑改为如下就能够了:

#include //信号处理所需要的头文档
int main(int argc, char * argv[]){
  //其他所需要的变量声明  
  sigset_t sig_set,sig_pending;
  启动几个子线程  
  ...........

 
  //主线程进入睡眠,等待信号到达后跳出睡眠  
  while(1){
          sigpending(&sig_pending);
          if(sigismember(&sig_pending, SIGTERM)||
                    sigismember(&sig_pending,SIGINT)){
                break;
          }
          sleep(2);
  }

  //子线程退出情理
  ................
  return 0;

}

喜欢本文,那就收藏到:

    Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网
相关评论  我也要评论
还没有关于此文章的相关评论!
  • 昵称: (为空则显示guest)
  • 评论分数: ★ ★ ★★★ ★★★★ ★★★★★
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
  • 导航
    赞助商
    文章类别
    订阅