2.Utilization of Error Dump System

2.1Interuppt C Runtime error on minidump system

Basically minidump system does not dectect error that called from out - of - the - ragne error on STL or pure virtual function on run time.

Minidump only handles Structured Exception.Error on above are assimilating at C runtime library.

Therefore it has to pass to Structured Exception before it assimilated on C runtime library which mean you need to relay it for leaving error dump.

Here is how to leave error dump

"Pure virtual function called" relay error to minidump

void myPurecallHandler(void)
{
    printf("In _purecall_handler.");

    int* a = 0;
    *a = 1; // Occuring chrash. relay to minidump. 
}

int main()
{
    /* pure virtual function called relay error handler to user defined function.
    You need to put it for firstime when you start program.  */    _set_purecall_handler(myPurecallHandler);
    ...
}

relay “out of the range error” on STL to mini dump system

Caution!!- You need to ignore retportType == _CRT_WARN because if _CrtSetReportHook use ATLTRACE, it may enter to fixed function.

int YourReportHook(int reportType, char *message, int *returnValue)
{
    // Ignore _CRT_WARN or 0
    if (reprotType != _CRT_WARN)
    {
        int* a = 0;
        *a = 1; // Occuring crash. relay to minidump
    }

    return 1;
}

int main()
{
    /* relay handler of C runtime library error to user defined function.
    You need to put it for firstime when you start program.  */    _CrtSetReportHook(YourReportHook);

    std::vector<int> a;
    a[1] = 0; // Testing error handler is relayed or not
}

2.2Pauseless error dump system (Exception Logger)

ProudNet provides the function that keeps recording error directory without shutting down the program in case of error in the program. This is called Pauseless error dump system (Exception Logger).

In case of crash at a general game server, program re-starts right after recording the error history (please refer to 7. Tutorial for Error Dump System Construction) But in case it is absolutely necessary, the game server is kept operating without re-starting as error situation is maintained. You need to pay special attention because it is very dangerous for the server program whose memory has been damaged to be operated continuously.

Check list before creating pauseless error dump system.

Example of creating pauseless error dump system.

Note


•It is operated at the version of Windows XP/ Windows 2003 Server or later.

•Performance of the program might become worse due to overload of log history in case of using CExceptionLogger class along with AtlTrace() or DebugOutputString().

Example of this source file is in <installation folder>\Sample\SimpleExceptionLogger.

#include "stdafx.h"
#include <atlpath.h>
#include "../../include/DumpCommon.h"
#include "../../include/MiniDumper.h"

using namespace Proud;

class CIExceptionLoggerDelegate : public IExceptionLoggerDelegate
{
    public:
    virtual String GetDumpDirectory()
    {
        return L"";
    }
};

CIExceptionLoggerDelegate g_loggerInfo;

void AccessViolation()
{
    try
    {
        int* a = 0;

        // 이 루틴은 크래쉬를 의도적으로 발생시킵니다.
        // This routine incurs crash on purpose.
        // 该例程将会故意造成崩溃。
        // このルーティンはクラッシュを意図的に発生させます
        *a = 1;
    }
    catch (...) // catch(...) syntax itself is the usable C++ keyword!
    {
        // 위 try 구문에 의해 크래쉬가 발생할 경우
        // 프로그램이 종료되지 않고 여기로 실행 지점이 오게 됩니다.
        // 한편 exception logger에 의해 오류 로그가 파일로 남게 됩니다.
        // When crash occurs by the above try syntax,
        // the execution point moves to here without terminating the program.
        // At the same time, exception logger leaves an error log file.
    }
}

void main(int argc, char* argv[])
{
    int menu = 0;
    CExceptionLogger::Instance().Init(&g_loggerInfo);

    while (1)
    {
        puts("MENU: 1. Access Violation('a')");
        printf("> ");

        menu = getchar();

        switch (menu)
        {
        case 'a':
            AccessViolation();
            break;
        default:
            break;
        }
    }
}

2.3Logging the current status of process in dump file

There is a function in Part X. MiniDump (Error Dump System) that logs the current status of process in a dump file even though no error has occurred.

When you open the saved dump file along with a debug information file (.pdb) generated when building the associated program, you can view the source codes of process on execution.

그림 2-1With this function, you can log the current status of process even at difficult debugging situation.

When Proud.CMiniDumper.WriteDumpFromHere is called, it saves call stacks of every thread inside of process up until the call is made into a dump file.

2.4Error dump system (MiniDump) creation at NTService.

Check list before creating error dump system (MiniDump) at NTService.

Example of error dump system (MiniDump) at NTService.

#include "stdafx.h"
#include <atlpath.h>
#include "../../include/DumpCommon.h"
#include "../../include/MiniDumper.h"
#include "../../include/NTService.h"
#include "../../include/ProudNetServer.h"
#include "conio.h"

using namespace std;
using namespace Proud;

const int _MAX_PATH2 = 8192;
#define _COUNTOF(array) (sizeof(array)/sizeof(array[0]))

void GetDumpFilePath(LPWSTR output)
{
    WCHAR path[_MAX_PATH2];
    WCHAR drive[_MAX_PATH2];
    WCHAR dir[_MAX_PATH2];
    WCHAR fname[_MAX_PATH2];
    WCHAR ext[_MAX_PATH2];
    WCHAR module_file_name[_MAX_PATH2];

    GetModuleFileNameW(NULL, module_file_name, _COUNTOF(module_file_name));
    _tsplitpath_s(module_file_name, drive, _MAX_PATH2, dir, _MAX_PATH2, fname, _MAX_PATH2, ext, _MAX_PATH2);
    _tmakepath_s(path, _MAX_PATH2, drive, dir, L"", L"");
    wsprintf(output, L"%s%s.DMP", path, fname);
};

int g_ServerPort = 33334;

void AccessViolation()
{
    int* a = 0;
    *a = 1;
}

class CMySvrEvent: public INTServiceEvent
{
public:
    virtual void Log(int type, LPCWSTR text)
    {
        _tprintf(L"%s\n", text);
    }

    virtual void Run()
    {
        // 윈도우 서비스 시작과 동시에 게임서버를 수행시킬 수 있는 코드를 작성합니다.
        // At the same time when Windows service gets started, design a code that can execute a game server.
        // 编写Windows服务启动的同时运行游戏引擎的代码。
        // ウィンドウサービススタートと同時にゲームサーバーを随行できるコードを作成します
        RefCount<CNetServer> srv(CNetServer::Create());
        CStartServerParameter p1;
        p1.m_tcpPorts.Add(g_ServerPort);
        
        ErrorInfoPtr err;
        
        bool result = srv->Start(p1, err);
        if (result == false)
        {
            printf("Server Start Error: %s\n",     StringW2A(ErrorInfo::TypeToString_Kor(err->m_errorType)));
            return;
        }
    
        puts("Game Server started.\n");
    
        while (1)
        {
            Sleep(100);
            if (_kbhit())
            {
                int ch = _getch();
                switch (ch)
                {
                case 27:
                    return;
                }
            }
    
            MSG msg;
    
            // 최대 일정 짧은 시간동안, 콘솔 입력, 윈도 메시지 수신, 메인 스레드 종료 중 하나를 기다린다.
            // Wait for one of console input, Windows message receiving or main thread shutting down in a short period of time.
            // 等待最短时间, 输入Console, 接收Windows消息, 终了主线程中一个。
            // 最大日程短い時間の間、コンソール入力、ウィンドウメッセージ受信、メインスレッド終了中一つを待ちます。
            MsgWaitForMultipleObjects(0, 0, TRUE, 100, QS_ALLEVENTS);
            if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
            {
                if (!GetMessage(&msg, NULL, NULL, NULL))
                    break;
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }

    virtual void Pause()
    {
        AccessViolation();
        printf("pause");
    }

    virtual void Stop()
    {
        printf("stop");
    }
    
    virtual void Continue()
    {
        printf("continue");
    }
};

CMySvrEvent g_svrEvent;

int wmain(int argc, WCHAR* argv[], WCHAR* envp[])
{
    int nRetCode = 0;
    
    WCHAR dumpFileName[_MAX_PATH2] = { 0, };
    GetDumpFilePath(dumpFileName);
    
    CMiniDumpParameter parameter;
    parameter.m_dumpFileName = dumpFileName;
    parameter.m_miniDumpType = SmallMiniDumpType;
    
    switch (CMiniDumper::Instance().Startup(parameter))
    {
    case MiniDumpAction_AlarmCrash:
        // 오류 발생으로 새로운 프로세스에서 덤프 파일을 생성한 후, 이 값이 return이 됩니다.
        // 생성된 덤프 파일을 메일로 보내거나 에러 창을 보이는 등 유저가 덤프 파일 생성 후, 처리해야할 작업을 처리해주시면 됩니다.

        // A dump file is created at a new process due to error occurrence and then this value will be returned.
        // After a user create a dump file, do works that need to be done such as sending a created dump file by email or showing an error window.

        // 因出现错误,在新的process中生成转储文件后该值将被返还。
        // 将生成的转储文件以邮件的形式发送,或可以看到 Error对话框的用户生成转存文件后,处理应处理的事即可

        // エラー発生により新しいプロセスからダンプファイルを生成した後、この値がreturnされます。
        // 生成されたダンプファイルをメールで送ったり、エラーメッセージが提示されるなどユーザーがダンプファイル生成後、処理すべきの作業をしてください。
        ...
        return nRetCode;

    case MiniDumpAction_DoNothing:
        // 유저 호출로 새로운 프로세스에서 덤프 파일을 생성한 후, 이 값이 반환됩니다.
        // 이 경우에는 아무것도 하지 말아야합니다.

        // After creating a dump file at a new process by calling a user, this value will be returned.
        // In this case, you should not do anything.

        // 因用户呼叫,在新的process中生成转储文件后,该值将被返还。
        // 在这种情况,不要做任何事情。.

        // ユーザー呼び出しにより新しいプロセスからダンプファイルを生成した後、この値が返還されます。
        // この場合何もしないでください。
        ...
        return nRetCode;

    default:
        // MiniDumpAction_None
        // 일반적으로 앱 실행 시, 이 값이 반환됩니다.
        // 여기서는 일반적으로 처리해야할 일을 처리해주시면 됩니다.

        // When executing apps, this value will be returned.
        // In this case, do works that generally need to be done.

        // 一般运行App时,该值将被返还。
        //在这里处理一般应处理的事情即可。

        // 一般的にアプリ実行後、この値が返還されます。
        // ここでは一般的に処理すべきの事を処理してください。
        ...
        break;
    }

    CNTServiceStartParameter param;
    param.m_serviceName = L"ProudNet NT Service Sample";
    param.m_serviceEvent = &g_svrEvent;

    CNTService::WinMain(argc, argv, envp, param);

    return nRetCode;
}

2.5Compile Setting for Error Dump System

To use Part X. MiniDump (Error Dump System), apply C++ compile setting as shown in the below picture.

그림 2-2Setting compile for the use of minidump

These settings can't be applied to Visual Studio 2003. Thus please select No then add /EHa on Configuration Properties->C/C++->Command Line->Additional Options.