/*
 * WaitQuitSignal.h
 *
 *  Created on: Aug 14, 2011
 *      Author: xian0617
 */

#ifndef WAITQUITSIGNAL_H_
#define WAITQUITSIGNAL_H_
#include <signal.h>
#include <time.h>
class WaitQuitSignal {
public:
	static void init();
	static bool wait(bool&flag);
private:
	static sigset_t m_wait_mask;
	static struct timespec m_time;
};

#endif /* WAITQUITSIGNAL_H_ */
/*
 * WaitQuitSignal.cpp
 *
 * Linux下的线程实质上是轻量级进程(light weighted process),线程生成时会生成对应的进程控制结构,
 * 只是该结构与父线程的进程控制结构共享了同一个进程内存空间。 同时新线程的进程控制结构将从父线程(进程)
 * 处复制得到同样的进程信息,如打开文件列表和信号阻塞掩码等。由于我们是在子线程生成之后修改了信号阻塞掩
 * 码,此刻子线程使用的是主线程原有的进程信息,因此子线程仍然会对SIGINT和SIGTERM信号进行反应,因此当
 * 我们用Ctrl+C发出了 SIGINT信号的时候,主进程不处理该信号,而子进程(线程)会进行默认处理,即退出。
 * 子进程退出的同时会向父进程(线程)发送SIGCHLD信号,表示子进程退出,由于该信号没有被阻塞,因此会导致
 * 主进程(线程)也立刻退出,出现了前述的运行情况。因而该问题的一个解决方法是在子线程生成前进行信号设置,
 * 或在子线程内部进行信号设置。
 *  Created on: Aug 14, 2011
 *      Author: xian0617
 */

#include <iostream>
#include "WaitQuitSignal.h"
sigset_t WaitQuitSignal::m_wait_mask;
struct timespec WaitQuitSignal::m_time;
//call this before thread create
void WaitQuitSignal::init(){
 try{
  signal(SIGKILL, SIG_IGN);
  sigemptyset(&m_wait_mask);
  sigaddset(&m_wait_mask, SIGINT);
  sigaddset(&m_wait_mask, SIGQUIT);
  sigaddset(&m_wait_mask, SIGTERM);
  pthread_sigmask(SIG_BLOCK, &m_wait_mask, 0);
 } catch (std::exception& e){
  std::cerr << "exception: " << e.what() << std::endl;
 }
 m_time.tv_sec=0;
 m_time.tv_nsec =0;
}
bool WaitQuitSignal::wait(bool &flag){
 try{
  siginfo_t sig ;
  switch(sigtimedwait(&m_wait_mask,&sig,&m_time)){
  case SIGINT:
  case SIGQUIT:
  case SIGTERM:
   flag=false;
   break;
  default:
   break;
  }

 } catch (std::exception& e){
  std::cerr << "exception: " << e.what() << std::endl;
 }
 return flag;
}


posted on 2012-06-11 12:03  未雨愁眸  阅读(1773)  评论(0编辑  收藏  举报