some code of debug mode

#include "common.h"

#include "CIniFile.h"
#include "CRecordCfg.h"
#include "CFileFactory.h"
#include "CCtrlThread.h"
#include "CThread.h"
#include "CDeleteThread.h"
#include "CSendFileinfoThread.h"
#include "CConfigExt.h"
#include "CUtil.h"
#include "CStringExt.h"


//=================================================
//静态(本地)全局变量
//=================================================
//子进程ID
static int g_nPID = 0;

//退出标志
static char g_cExitFalg = '\0';

//是否将解析后的配置输出到文件
static int g_nGenerateCfg = -1;

//日志级别
static int g_nLogModId = 0;

//处理输入参数、提示用法
static int doParams(int argc, char* argv[]);
static int usage();
static void displayAppInfo();

//子进程
static void InitLog();
static void SetLogConfig(CConfigExt* pConf);
static void* CheckStatusThread(void* Arg);
static int mainFun(int argc, char** argv);

//启动视频转码服务
//static void StartTransmitService();

//调试用,在发生崩溃时抓取堆栈信息
#define DEBUG_BT

static void Debug_Printf_FrameInfos();
static void dump_debug(int signo);

//=================================================
//全局对象
//=================================================
CCtrlThread* g_pCtrlThread = NULL;
CRecordCfg* g_pRecordCfg = NULL;
CConfigExt* g_pConfigExt = NULL;



//=================================================
//主程序实现
//=================================================
int main(int argc, char** argv)
{
g_cExitFalg = '\0';

int ret = doParams(argc, argv);
if (ret <= 0)
{
if (ret < 0)
{
usage();
}
return 0;
}

if ((g_nPID = fork()) == 0)/*executed by child process*/
{
mainFun(argc, argv);
}
else/*executed by parent process*/
{
pthread_attr_t attr;
pthread_t Thrd;
struct sched_param SchedParam;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
sched_getparam(0, &SchedParam);
SchedParam.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_setschedparam(&attr, &SchedParam);

int s = pthread_create(&Thrd, &attr, CheckStatusThread, NULL);
if (s != 0)
{
printf("pthread_create() failed. %s\n", strerror(errno));
}
}

//TEST_CMMB();
//wait until the user entered 'q' to exit the main process(and the child process).
while (g_cExitFalg != 'q')
{
scanf("%c", &g_cExitFalg);
sleep(1);
}
kill(g_nPID, SIGKILL);

return 0;
}

int mainFun(int argc, char** argv)
{
displayAppInfo();

//调试信息
#ifdef DEBUG_BT
Debug_Printf_FrameInfos();
#endif

//初始化日志模块
InitLog();
LOG(LOG_TYPE_NOTICE, "[Thread:0x%x] mainFun Start.", pthread_self());

//读取内部配置
g_pConfigExt = new CConfigExt(CUtil::GetAppPath() + CONF_FILE_EXT);
if (g_pConfigExt != NULL)
{
if (g_pConfigExt->Parse())
{
g_pConfigExt->Dump();

//重新设置日志级别
SetLogConfig(g_pConfigExt);

CUtil::SetLocalPort(g_pConfigExt->m_nLocalPort);
}
else//内部配置文件解析失败,采用默认配置
{
// delete g_pConfigExt;
// g_pConfigExt = NULL;
//
// LOG(LOG_TYPE_FATAL, "配置文件解析失败,程序退出.");
// exit(EXIT_FAILURE);
}
}

//初始化数据库环境
CMysqlDatabase::InitLibrary();

//控制线程:控制所有线程的运行、停止
g_pCtrlThread = new CCtrlThread();
CThread * pThread = new CThread(g_pCtrlThread);
g_pCtrlThread->m_pThread = pThread;

//发送文件信息线程
CSendFileinfoThread * pSendFileInfoThread = new CSendFileinfoThread();
CThread * pThreadSendFileInfo = new CThread(pSendFileInfoThread);
pSendFileInfoThread->m_pThread = pThreadSendFileInfo;
g_pCtrlThread->m_pSendinfoThread = pSendFileInfoThread;

//读取配置文件
CObjectFactory* pFac = new CFileFactory(CUtil::GetAppPath() + CONF_FILE);
if (pFac == NULL)
{
LOG(LOG_TYPE_ERROR, "pFac = NULL.");
exit(EXIT_FAILURE);
}

//全局配置对象
g_pRecordCfg = new CRecordCfg(pFac);
if (!g_pRecordCfg->ParseObjects())
{
LOG(LOG_TYPE_FATAL, "配置文件解析失败,程序退出.");

delete g_pRecordCfg;
delete pFac;
delete g_pCtrlThread;

exit(EXIT_FAILURE);
}

//初始化数据库链接
CMysqlInfo* pMysqlInfo = g_pRecordCfg->m_pGlobal->m_pMysqlInfo;
if (pMysqlInfo != NULL)
{
CMysqlDatabase* pDb = CMysqlDatabase::GetInstance();
pDb->Init(pMysqlInfo);
}

//构造RecordMdoule对象
if (!g_pRecordCfg->NewChannelModules())
{
LOG(LOG_TYPE_FATAL, "GetChannelModules() failed.");

delete g_pRecordCfg;
delete pFac;
delete g_pCtrlThread;

exit(EXIT_FAILURE);
}

//检查通道数
if (g_pRecordCfg->m_pRecordModules.size() <= 0)
{
LOG(LOG_TYPE_ERROR, "No Valid RecordModule");

//程序空跑,所有功能线程(获取配置线程,删除线程)继续运行
// delete g_pRecordCfg;
// delete pFac;
// exit(EXIT_FAILURE);
}

//查看对象数据
g_pRecordCfg->DumpObjects(g_nGenerateCfg);

//删除文件线程
CDeleteThread * pDeleteThread = new CDeleteThread(g_pRecordCfg);
CThread * pThreadDelete = new CThread(pDeleteThread);
pDeleteThread->m_pThread = pThreadDelete;
g_pCtrlThread->m_pDeleteThread = pDeleteThread;

//配置更新线程
CConfigThread* pConfigThread = new CConfigThread;
CThread * pThreadConfig = new CThread(pConfigThread);
pConfigThread->m_pThread = pThreadConfig;
g_pCtrlThread->m_pConfigThread = pConfigThread;

CSnmpThread* pSnmpThread = new CSnmpThread;
CThread* pThreadSnmp = new CThread(pSnmpThread);
pSnmpThread->m_pThread = pThreadSnmp;
g_pCtrlThread->m_pSnmpThread = pSnmpThread;

//启动所有线程
g_pCtrlThread->setRecordCfg(g_pRecordCfg);
pThread->start();

SNMP_NOTIFY("Record Started!");

//主线程:DO NOTHING
while (1)
{
sleep(1000);
}
CMysqlDatabase::DeInitLibrary();
return 0;
}

void displayAppInfo()
{
printf("**********************************************************\n");
printf("录制程序,版权所有.\n");
printf("*********** *********** ***********\n");
printf("*********** *********** ***********\n");
printf("** ** ** \n");
printf("** ** ** \n");
printf("*********** ** ** \n");
printf("*********** ** ** \n");
printf("** ** ** \n");
printf("** ** ** \n");
printf("** *********** ** \n");
printf("** *********** ** \n\n");
printf("CopyRight ©2011,2012, All rights reserved.\n");
printf("ShangHai Figure-IT, Inc.\n");
printf("**********************************************************\n");
printf("程序版本:\t%s\n", strVession.c_str());
printf("编译日期:\t%s %s\n", __DATE__, __TIME__);
printf("gcc版本:\t%s\n", __VERSION__);
printf("运行平台:\t%s\n", strPlatform.c_str());
printf("启用模块:\n");
for(unsigned int i=0; i<(sizeof(strEnableModules)/sizeof(strEnableModules[0])); i+=2)
{
printf("%s\t%s\n", strEnableModules[i].c_str(), strEnableModules[i+1].c_str());
}

printf("禁用模块:\n");
for(unsigned int i=0; i<(sizeof(strDisableModules)/sizeof(strDisableModules[0])); i+=2)
{
printf("%s\t%s\n", strDisableModules[i].c_str(), strDisableModules[i+1].c_str());
}
printf("\n");
}

int usage()
{
printf("usage: \e[1mRecord\e[0m [\e[4moption\e[0m]\n");
printf("\e[34m[\e[4m-version\e[0m\e[34m]:\e[0m\tprint the version and exit.\n");
printf("\e[34m[\e[4m-help\e[0m\e[34m]:\e[0m\tprint this usage and exit.\n");
printf("\e[34m[\e[4m-gen\e[0m\e[34m]:\e[0m\tgenerate the parsed configure to a file named 'config.sys.gen'.\n");

return 0;
}

void pr_exit(int status)
{
if (WIFEXITED(status))
{
printf("normal termination, exit status =%d\n", WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
{
printf("abnormal termination, killed by signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)\n" : "(No core file generated)\n");
#else
"WCOREDUMP not defined.\n");
#endif
}
else if (WIFSTOPPED(status))
{
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
}

void* CheckStatusThread(void* Arg)
{
printf("[Thread] CheckStatusThread Start.\n");

int nStatus = 0;
while (g_cExitFalg != 'q')
{
int n = waitpid(g_nPID, &nStatus, 0);

//continue;
if (n <= 0)
{
if (errno == ECHILD)
{
}
}
else
{
pr_exit(nStatus);

printf("********************************************************\n");
printf("NOTIFITION: programme exited!function will restart now!\n");
printf("********************************************************\n");

if ((g_nPID = fork()) == 0)
{
mainFun(0, NULL);
}
}
}

return NULL;
}

int doParams(int argc, char* argv[])
{
int ret = 1;
if (argc > 1)
{
int i = 1;
for (; i < argc; i++)
{
if ((strcasecmp(argv[i], "-version") == 0) || (strcasecmp(argv[i], "-v") == 0))
{
displayAppInfo();
ret = 0;
}
else if ((strcasecmp(argv[i], "-help") == 0) || (strcasecmp(argv[i], "-h") == 0))
{
usage();
ret = 0;
}
else if ((strcasecmp(argv[i], "-gen") || (strcasecmp(argv[i], "-g") == 0)))
{
g_nGenerateCfg = 1;
}
else
{
ret = -1;
}
}
}

return ret;
}

void InitLog()
{
g_nLogModId = CFitLog::Instance()->registerMod("Record");
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_NOTICE);
CFitLog::Instance()->enableStdout();
CFitLog::Instance()->enableRollingFileOutput(CUtil::GetAppPath() + "Record.log", 50 * 1024 * 1024, 3);
//CFitLog::Instance()->enableMemOutput();
}

void SetLogConfig(CConfigExt* pConf)
{
if(pConf == NULL)
{
return;
}

string strLevel = pConf->m_strLogLevel;
if (strLevel == "LOG_DEBUG")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_DEBUG);
}
else if (strLevel == "LOG_INFO")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_INFO);
}
else if (strLevel == "LOG_NOTICE")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_NOTICE);
}
else if (strLevel == "LOG_WARN")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_WARN);
}
else if (strLevel == "LOG_ERROR")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_ERROR);
}
else if (strLevel == "LOG_FATAL")
{
CFitLog::Instance()->setModPriority(g_nLogModId, LOG_TYPE_FATAL);
}
else
{
printf("Invalid log level:'%s'\n", strLevel.c_str());
}

if(pConf->m_nEnableLogSocket != 0)
{
CFitLog::Instance()->enableNetworkOutput("Record", LOG_NET_IP, LOG_NET_PORT, pConf->m_strLogSocketAddr);
}
}

void dump_debug(int signo)
{
void *array[30] = {0};
size_t size;
char **strings = NULL;
size_t i;

string strFile = CUtil::GetAppPath() + "signal.log";
FILE* pf = fopen(strFile.c_str(), "w");//每次清空,防止程序不断重启导致signal.log文件过大

size = backtrace (array, 30);
strings = backtrace_symbols (array, size);
if(strings != NULL)
{
fprintf (stderr,"[%s] get SIGSEGV[%d] signel.\n", CDateTime::GetCurrentTime().c_str(), signo);
fprintf (stderr,"[%s] Obtained %zd stack frames.\n", CDateTime::GetCurrentTime().c_str(), size);
if(pf != NULL)
{
fprintf (pf, "[%s] get SIGSEGV[%d] signel.\n", CDateTime::GetCurrentTime().c_str(), signo);
fprintf (pf, "[%s] Obtained %zd stack frames.\n", CDateTime::GetCurrentTime().c_str(), size);
fflush(pf);
}

for (i = 0; i < size; i++)
{
fprintf (stderr,"[%s] %s\n", CDateTime::GetCurrentTime().c_str(), strings[i]);
fflush(stderr);

if(pf != NULL)
{
fprintf (pf,"[%s] %s\n", CDateTime::GetCurrentTime().c_str(), strings[i]);
fflush(pf);
}
}
}

if(pf != NULL)
{
fclose(pf);
pf = NULL;
}
free (strings);

exit(0);
}

void Debug_Printf_FrameInfos()
{
signal(SIGSEGV, dump_debug);
signal(SIGABRT, dump_debug);
}

posted @ 2012-09-09 21:47    阅读(796)  评论(0编辑  收藏  举报