监听获取程序退出事件(Linux、Windows、Java、C++)
监听程序退出事件,主要是用于程序的优雅退出。
下面针对Java、C++在Windows、Linux下的处理分别进行介绍.
1.Java监听程序退出事件
Java本身是跨平台的,不必关系Windows还是Linux。具体做法如下:
通过Runtime.getRuntime().addShutdownHook(Thread t);添加一个监控线程,在该程序退出时会调用Thread的run方法。不得不说Java真的很方便。
我实现的一个例子。
public class RTMServer extends Thread{
private MessageServer msg_server = null;
private ThriftServer thrift_server = null;
public RTMServer()
{
this.setName("RTMServer");
}
public void start_server()
{
// 添加程序关闭监听线程
Runtime.getRuntime().addShutdownHook(this);
msg_server = new MessageServer();
msg_server.start();
thrift_server = new ThriftServer("ThriftServer");
thrift_server.start();//该方法会阻塞
}
/*
* 继承Thread
* 用于在程序关闭时释放资源。
* @see java.lang.Thread#run()
*/
public void run()
{
if(thrift_server != null)
{
thrift_server.close();
}
if(msg_server != null)
{
msg_server.close();
}
VMManager.instance.destroyPool();
}
public static void main(String[] args) {
// 初始化日志
LogUtil.init();
RTMServer server = new RTMServer();
server.start_server();
}
}
是不是很简单呢?
2.C++ Linux下监听程序退出事件
主要通过Linux的signal进行判断,程序启动时通过
sigaction(SIGHUP,&act,NULL)
设置要捕获的信号,则发生相应的信号时就会被
handle_signal(int n,struct siginfo *siginfo,void *myact)
捕获。
linux退出信号主要有SIGHUP,SIGINT,SIGQUIT,SIGTERM,即1,2,3,15
下面是我的一个封装。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
class SignalHandler{
public:
SignalHandler();
public:
// 程序退出时的函数操作
static void handle_signal(int n,struct siginfo *siginfo,void *myact);
};
SignalHandler * g_exit_handler = NULL;
SignalHandler::SignalHandler()
{
/** install signal use sigaction **/
struct sigaction act;
sigemptyset(&act.sa_mask); /** 清空阻塞信号 **/
act.sa_flags=SA_SIGINFO; /** 设置SA_SIGINFO 表示传递附加信息到触发函数 **/
act.sa_sigaction=handle_signal;
if(sigaction(SIGHUP,&act,NULL) < 0 // 1
|| sigaction(SIGINT,&act,NULL) < 0 // 2
|| sigaction(SIGQUIT,&act,NULL) < 0 // 3
//|| sigaction(SIGKILL,&act,NULL) < 0 // 9
|| sigaction(SIGTERM,&act,NULL) < 0 // 15
)
{
LOG4CPP(LOG_LEVEL_ERROR,"install signal handler error");
}
}
void SignalHandler::handle_signal(int n,struct siginfo *siginfo,void *myact)
{
LOG4CPP(LOG_LEVEL_WARN,"SIGNAL received: signo=%d errno=%d code=%d ",siginfo->si_signo,siginfo->si_errno,siginfo->si_code);
if(siginfo->si_signo == 1
|| siginfo->si_signo == 2
|| siginfo->si_signo == 3
|| siginfo->si_signo == 9
|| siginfo->si_signo == 15)
{
//程序退出,进行退出处理操作
exit(0);
}
}
在主程序启动时创建Handler(),则程序退出时会捕获到相应的信号
g_exit_handler = new SignalHandler();
3.C++ Windows下监听程序退出事件
windows下捕获程序退出事件主要通过
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ctrlhandler, true )
其中ctrHandler是一个回调函数,在退出时会触发该函数。
具体的实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
bool ctrlhandler( DWORD fdwctrltype );
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ctrlhandler, true ) )
{
}
else
{
LOG4CPP(LOG_LEVEL_ERROR,"install signal handler error");
}
bool ctrlhandler( DWORD fdwctrltype )
{
switch( fdwctrltype )
{
// handle the ctrl-c signal.
case CTRL_C_EVENT:
//printf( "ctrl-c event\n\n" );
//return( true );
// ctrl-close: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
//printf( "ctrl-close event\n\n" );
//return( true );
// pass other signals to the next handler.
case CTRL_BREAK_EVENT:
//printf( "ctrl-break event\n\n" );
//return false;
case CTRL_LOGOFF_EVENT:
//printf( "ctrl-logoff event\n\n" );
//return false;
case CTRL_SHUTDOWN_EVENT:
//printf( "ctrl-shutdown event\n\n" );
//return false;
//清理
return true;
default:
return false;
}
}
4.总结
其实原理都差不多,就是在程序启动时需要设置一个“程序退出监听器”,只不过在windows、linux下C++、Java的监听器不同而已。
赞 (0)