后台任务性质的程序无法确定的原因处于不可恢复状态时自动重新启动进程.
主要是应对Berkeley DB DB_RUNRECOVERY错误特例的情况.
处理步骤:
程序更新:
.更新bbox.dll
.把restart_proc.exe复制到服务器主目录下
配置修改:
bbox.conf增加以下配置项:
服务器程序在判定不可恢复时,启动restart_proc程序,由它立即重新启动服务程序。
restart_proc代码:
实现参考资料:
主要是应对Berkeley DB DB_RUNRECOVERY错误特例的情况.
处理步骤:
程序更新:
.更新bbox.dll
.把restart_proc.exe复制到服务器主目录下
配置修改:
bbox.conf增加以下配置项:
<debug_flag>1</debug_flag> <!--用于诊断的配置项,bit0-回路时是否重新启动 -->
服务器程序在判定不可恢复时,启动restart_proc程序,由它立即重新启动服务程序。
restart_proc代码:
///< 启动时创建管道,启动者通过管道与本进程通信,发送需要启动的进程ID
///< 本进程根据进程ID,确定执行程序.
///< 关闭进程
///< 重新启动进程
int _tmain(int argc, _TCHAR* argv[]) {
HANDLE pipe = CreateNamedPipe(
"\\\\.\\pipe\\restart_proc_pipe", // name of the pipe
PIPE_ACCESS_INBOUND, // 1-way pipe -- send only
PIPE_TYPE_BYTE, // send data as a byte stream
1, // only allow 1 instance of this pipe
0, // no outbound buffer
0, // no inbound buffer
0, // use default wait time
NULL // use default security attributes
);
if (pipe == NULL || pipe == INVALID_HANDLE_VALUE) {
return 1;
}
// This call blocks until a client process connects to the pipe
BOOL result = ConnectNamedPipe(pipe, NULL);
if (!result) {
CloseHandle(pipe); // close the pipe
return 1;
}
// The read operation will block until there is data to read
char buffer[1024];
DWORD numBytesRead = 0;
result = ReadFile(
pipe,
buffer, // the data from the pipe will be put here
1024 * sizeof(char), // number of bytes allocated
&numBytesRead, // this will store number of bytes actually read
NULL // not using overlapped IO
);
bool ret = false;
if (result) {
buffer[numBytesRead / sizeof(char)] = '\0'; // null terminate the string
vector<string> vs;
SplitString(buffer,vs,',');
DWORD pid = atoi(vs[0].c_str());
string cmd_para = vs[1];
HANDLE hModuleSnap = NULL;
MODULEENTRY32 me32 = {0};
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hModuleSnap == INVALID_HANDLE_VALUE)
return -1;
me32.dwSize = sizeof(MODULEENTRY32);
bool bFound= false;
if (Module32First(hModuleSnap, &me32)) {
do {
if (me32.th32ProcessID == pid) {
bFound = TRUE;
}
}
while (!bFound && Module32Next(hModuleSnap, &me32));
}
CloseHandle (hModuleSnap);
if (!bFound)
return -1;
string cmd = string(me32.szExePath)+string(" ")+ cmd_para;
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
while(1) {
DWORD exit_code = 0;
if (!GetExitCodeProcess(handle,&exit_code))
break;
if (exit_code!=STILL_ACTIVE)
break;
ret = TerminateProcess(handle,0);
}
ExecuteCmd(cmd.c_str(),true,false,0);
}
CloseHandle(pipe);
return 0;
}
调用代码:
/
int ExecuteCmd(const char *cmdStr,bool show_window,bool wait_fin,HANDLE *handle)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
GetStartupInfo(&si);
si.cb = sizeof(STARTUPINFO);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.dwFlags = STARTF_USESTDHANDLES;
if (!show_window) {
si.wShowWindow = SW_HIDE;
si.dwFlags |= STARTF_USESHOWWINDOW;
}
ZeroMemory( &pi, sizeof(pi) );
if (!CreateProcess(NULL,const_cast<char*>(cmdStr) ,NULL,NULL,FALSE,NULL,NULL,NULL,&si,&pi)) {
DWORD ErrorCode = GetLastError();
return -1;
}
DWORD result = 0;
if (wait_fin) {
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess(pi.hProcess,&result);
}
if (handle) {
*handle = pi.hProcess;
}
return result;
}
int restart() {
HANDLE handle = 0;
if (ExecuteCmd("restart_proc",true,false,&handle))
return -1;
HANDLE pipe = INVALID_HANDLE_VALUE;
while(pipe == INVALID_HANDLE_VALUE) {
pipe = CreateFile(
"\\\\.\\pipe\\restart_proc_pipe",
GENERIC_WRITE, // only need read access
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
Sleep(1000);
}
DWORD dwPID = GetCurrentProcessId();
char data[32];
sprintf(data,"%lu,-d",dwPID);
DWORD numBytesWritten = 0;
int result = WriteFile(
pipe, // handle to our outbound pipe
data, // data to send
strlen(data),
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);
CloseHandle(pipe);
WaitForSingleObject( handle, INFINITE );
return 0;
}
bbox调用(CBBoxPlugin::HandleInput_i函数中)
if (IsIncomingMsg(pwm)) { ///< 来自外部的消息,如果是非本地机构,则表示非预期的消息
if ((tt==1&&!IsLocalOrg(tid))||(tt == 2 && !IsLocalOrg(ORGID_IN_USERSERIAL(tid)))) {
nlogger_->log(LO_STDOUT|LO_FILE,SEVERITY_ERROR,"CBBoxPlugin::HandleInput_i来自外部的非本地消息 \n");
if (debug_flag_&1) {
restart(); ///< 重新启动进程
return -1;
}
}
}
实现参考资料:
Introduction to Win32 Named Pipes (C++)
http://www.avid-insight.co.uk/2012/03/introduction-to-win32-named-pipes-cpp/