zoukankan      html  css  js  c++  java
  • 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);
    }

  • 相关阅读:
    2021年年度总结——命运与轮回思考
    Kafka消费端数据过滤方案
    Vue.js知识点汇集
    The POM for is missing .....no dependency information available
    Knife4j 自定义参数解析
    Java List<String> IndexOf(object e)坑
    ES6获取对象数组属性最大最小值
    VM虚拟机(Windows server 2019)分区
    uniapp本地文件的路径
    JS墨卡托坐标与经纬度互转
  • 原文地址:https://www.cnblogs.com/chutianyao/p/2677948.html
Copyright © 2011-2022 走看看