Quantcast
Channel: CodeSection,代码区,Linux操作系统:Ubuntu_Centos_Debian - CodeSec
Viewing all articles
Browse latest Browse all 11063

零停重启程序工具Huptime研究

$
0
0

零停重启程序工具Huptime研究

8.系统调用钩子辅助 6

9.被勾住系统调用 exit 6

10.被勾住系统调用 listen 7

11.SymbolVersioning 8

12.勾住 bind 等系统调用 10

1.官网

https://github.com/amscanne/huptime

2.功能

零停重启目标程序,比如一个网络服务程序,不用丢失和中断任何消息实现重新启动,正在处理的消息也不会中断和丢失,重启的方法是给目标程序的进程发SIGHUP信号。

3.环境要求

由于使用了Google 牛人 TomHerbert 为 linux 内核打的补丁 SO_REUSEPORT特性,因此要求Linux 内核版本为 3.9 或以上, SO_REUSEPORT允许多个进程监听同一IP 的同一端口。

4.实现原理

利用 SIGHUP+SO_REUSEPORT+LD_PRELOAD ,通过LD_PRELOAD将自己(huptime.so)注入到目标进程空间。

使用 python 脚本 huptime 启动时会设置 LD_PRELOAD ,将 huptime.so 注入到目标 程序的进程空间。

huptime.so 启动时会执行 setup函数,在 setup 中会创建一个线程 impl_restart_thread用于重启目标程序的进程,另外还会安装信号SIGHUP的处理器sighandler用于接收零重启信号 SIGHUP :

staticvoid__attribute__(( constructor ))

setup (void)

{

#definelikely(x)__builtin_expect(!!(x),1)

if(likely(initialized)) //只做一次

return;

initialized=1;

#define GET_LIBC_FUNCTION (_name)\

libc ._name= get_libc_function <_name##_t>(#_name,&_name)

//初始化全局变量libc,让其指向GLIBC库的bind等

GET_LIBC_FUNCTION( bind ); //libc.bind=dlsym(RTLD_NEXT,bind);//系统的bind

GET_LIBC_FUNCTION( listen );

GET_LIBC_FUNCTION( accept );

GET_LIBC_FUNCTION( accept4 );

GET_LIBC_FUNCTION( close );

GET_LIBC_FUNCTION( fork );

GET_LIBC_FUNCTION( dup );

GET_LIBC_FUNCTION( dup2 );

GET_LIBC_FUNCTION( dup3 );

GET_LIBC_FUNCTION( exit );

GET_LIBC_FUNCTION( wait );

GET_LIBC_FUNCTION( waitpid );

GET_LIBC_FUNCTION( syscall );

GET_LIBC_FUNCTION( epoll_create );

GET_LIBC_FUNCTION( epoll_create1 );

#undefGET_LIBC_FUNCTION

impl_init(); //安装信号SIGHUP处理器、创建重启线程等

}

template

staticFUNC_T

get_libc_function (constchar*name,FUNC_Tdef)

{

char*error;

FUNC_Tresult;

/*Clearlasterror(ifany).*/

dlerror();

/*Trytogetthesymbol.*/

result=(FUNC_T)dlsym( RTLD_NEXT ,name);

error=dlerror();

if(result==NULL||error!=NULL)

{

fprintf(stderr,"dlsym(RTLD_NEXT,\"%s\")failed:%s",name,error);

result=def;

}

returnresult;

}

5.SIGHUP 信号处理

//信号SIGHUP处理函数,作用是通过管道通知重启线程 impl_restart_thread ,

//这里其实可以考虑使用eventfd替代pipe

staticvoid*impl_restart_thread(void*);

void

sighandler (intsigno)

{

/*Notifytherestartthread.

*Wehavetodothisinaseparatethread,because

*wehavenoguaranteesaboutwhichthreadhasbeen

*interruptedinordertoexecutethissignalhandler.

*Becausethiscouldhavehappenedduringacritical

*section(i.e.locksheld)wehavenochoicebutto

*firetherestartasycnhronouslysothatittoocan

*grablocksappropriately.*/

if(restart_pipe[1]==-1)

{

/*We'vealreadyrun.*/

return;

}

while(1)

{

chargo='R';

intrc= write (restart_pipe[1],&go,1); //通知重启线程

if(rc==0)

{

/*Wat?Tryagain.*/

continue;

}

elseif(rc==1)

{

/*Done.*/

libc.close(restart_pipe[1]); restart_pipe[1]=-1;

break;

}

elseif(rc<0&&(errno==EAGAIN||errno==EINTR))

{

/*Goagain.*/

continue;

}

else

{

/*Shit.*/

DEBUG("Restartpipefubared!?Sorry.");

break;

}

}

}

6.重启线程

void*

impl_restart_thread (void*arg)

{

/*Waitforoursignal.*/

while(1)

{

chargo=0;

intrc= read (restart_pipe[0],&go,1); //等待SIGHUP信号

if(rc==1)

{

/*Go.*/

break;

}

elseif(rc==0)

{

/*Wat?Restart.*/

DEBUG("Restartpipeclosed?!");

break;

}

elseif(rc<0&&(errno==EAGAIN||errno==EINTR))

{

/*Keeptrying.*/

continue;

}

else

{

/*Realerror.Let'srestart.*/

DEBUG("Restartpipefubared?!");

break;

}

}

libc.close(restart_pipe[0]); restart_pipe[0]=-1;

/*Seenoteaboveinsighandler().*/

impl_restart (); //重启目标进程

returnarg;

}

7.重启目标程序

void

impl_restart (void)

{

/*Indicatethatwearenowexiting.*/

L(); //加锁

impl_exit_start ();

impl_exit_check ();

U(); //解锁

}

8.系统调用钩子辅助

funcs_timpl=

{

.bind=do_bind,

.listen=do_listen,

.accept=do_accept_retry,

.accept4=do_accept4_retry,

.close=do_close,

.fork=do_fork,

.dup=do_dup,

.dup2=do_dup2,

.dup3=do_dup3,

.exit=do_exit,

.wait=do_wait,

.waitpid=do_waitpid,

.syscall=(syscall_t)do_syscall,

.epoll_create=do_epoll_create,

.epoll_create1=do_epoll_create1,

};

funcs_t libc ; //目标程序的进程调用的实际是huptime中的 do_XXX 系列

9.被勾住系统调用 exit

staticvoid

do_exit (intstatus)

{

if(revive_mode==TRUE)

Viewing all articles
Browse latest Browse all 11063

Trending Articles