ProudNet.Eng
WebsiteProud ConsoleLanguage
  • ๐ŸŒProudNet
    • ProudNet Introduction
    • Download and Install
      • How to verify your ProudNet license
      • AMI
    • Project Settings
      • C++
      • C#
      • Mac Xcode
      • Linux
      • Unity3D
        • iOS Build
      • Unreal Engine 4
      • Running the PIDL Compiler
    • Using ProudNet
      • Server and Client
        • Utilization of Server
        • Utilization of Client
      • RMI
        • Utilization of RMI
      • PIDL
        • Utilization of PIDL
      • Event handling
      • Communication messages
      • P2P Communication
        • Using P2P communication
    • Utilization of ProudNet
      • How to use
      • Tips for performance
    • Using DB in ProudNet
      • DB Cache System ver.2
        • DB Cache Theory and Understanding
        • Install DB Cache and Set Up Network
        • DB Cache Server and Client
        • DB Cache usage and application
          • Utilization of DB Cache
      • ADO API
      • ODBC API
    • ProudNet Utility
  • ProudNet Note
    • Technical Notes
      • Main Loop
      • Setting up a server firewall
      • Encryption and decryption
      • What to do in case of an error
      • List of error messages
      • Synchronizing Character Position
      • Client-Server Communication
      • MiniDump (Error Dump System)
      • [Version 1.6] Server-to-Server LAN Communicator
    • Glossary
    • Sample examples
  • ๐ŸŒProud Service
    • Guide for Console
    • ProudChat
      • Download SDK
        • C++
        • C#
        • Unity3D
        • Unreal Engine 4
      • Features in Console
Powered by GitBook
On this page
  • Tutorial on building an error dump system
  • (1) Install the DbgHelp library
  • (2) Setting Visual Studio Compilation Options
  • (3) Example of creating a dump server
  • (4) Example of creating a dump client
  • (5) Creating a Dump Client for a Game Server
  • (6) Creating a Dump Client for Game Clients
  • Utilize an error dump system
  • - Intercepting C Runtime Errors from the Error Dump System
  • - Uninterrupted error dump system(Exception Logger)
  • - Leave a dump file of the current state of the process
  1. ProudNet Note
  2. Technical Notes

MiniDump (Error Dump System)

PreviousClient-Server CommunicationNext[Version 1.6] Server-to-Server LAN Communicator

Last updated 1 year ago

MiniDump (Error Dump System) is a feature provided by ProudNet that allows you to collect error information directly from the developer when a game client or game server crashes while playing an online game service in order to track the cause and take quick action.

Error information is collected in a *.DMP file, and developers can open the collected dump file in a development tool (such as Visual Studio) to see on which lines of the source file the crash occurred.

Tutorial on building an error dump system

The Building an Error Dump System tutorial included a game server and client.

(1) Install the DbgHelp library

Copy dbghelp.dll to the folder where your OS is installed (C:\Windows\system32) or to the program's current folder. dbghelp.dll is located in (ProudNet installation path)\ProudNet\Sample\Bin.

(2) Setting Visual Studio Compilation Options

For MiniDump (Error Dump System), you need to configure C++ compilation as below.

For Visual Studio 2003, you cannot set it as above, so you need to select 'No' and add /EHa in Configuration Properties -> C/C++ -> Command Line -> Additional Options.

(3) Example of creating a dump server

Responsible for collecting error information dump files sent by the dump client.

#include "../../../include/ProudNetServer.h"
#include "../../../include/DumpServer.h"
#include "MyDumpServer.h"
class CMyDumpServer : public IDumpServerDelegate
{
    ...
    virtual void OnStartServer(CStartServerParameter &refParam) override;
    String GetDumpFilePath(HostID clientEnid, const Proud::AddrPort& clientAddr, CPnTime dumpTime) override;
    void Run();
}
void main(int argc, char* argv[])
{
    CMyDumpServer srv;
    srv.Run();
}

(4) Example of creating a dump client

The dump client is responsible for sending dump files containing error information to the dump server.

If the process crashes, a temporary *.DMP dump file is automatically created and the error level information is attached to the Command Argument as the process runs again.

The error level information received as a command argument must be branched according to its severity, and in the case of MiniDumpAction_AlarmCrash, it is a critical error, so you must write code to send the dump file to the dump server.

(5) Creating a Dump Client for a Game Server

Since game servers typically do not provide a user UI, you will need to write code to send the *.DMP dump file directly to the dump server without popping up an error reporting dialog.

(6) Creating a Dump Client for Game Clients

Game clients typically have a user UI, so you will need to write code to prompt the game user if they want to send the generated *.DMP dump file to the dump server with an error report or skip it before proceeding.

Caution

  • We do not support dump clients on all mobile environments.

  • You must initialize the dump system using Proud.CMiniDumpParameter.

  • For the Unicode programming model, you can define a wide-character version of the main function, where the argv and envp parameters to the wmain function must use the wchar_t* format.

  • For MiniDumpAction_AlarmCrash, MiniDumpAction_DoNothing, you must terminate the program after branching because you can get stuck in an infinite loop by calling return.

#include "stdafx.h"
#include <atlpath.h>
#include "../../include/MiniDumper.h"
#include "../../include/DumpCommon.h"
 
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);
};
 
void AccessViolation()
{
    int* a = 0;
    *a = 1;
}
 
// void wmain(int argc, wchar_t* argv[])
int main(int argc, char* argv[])
{
    int nRetCode = 0;
    int *data = 0;
    int menu = 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;
    }
 
    while (1)
    {
        puts("MENU: 1. Access Violation('a')");
        printf("> ");
        
        menu = getchar();
 
        switch (menu)
        {
        case 'a':
            AccessViolation();
            break;
        default:
            break;
        }
    }
 
    return 0;
}

Utilize an error dump system

- Intercepting C Runtime Errors from the Error Dump System

Out-of-range errors in the STL or errors where a purely virtual function is called at runtime are not detected by the error dump system by default.

The error dump system only handles Structured Exceptions, because these errors are digested by the C runtime library. Therefore, you must divert them to Structured Exceptions before they can be digested by the C runtime library to leave an error dump.

Below is how to leave an error dump.

// Pure virtual function called" Bypassing errors to be received by the error dump system.
void myPurecallHandler(void)
{
    printf("In _purecall_handler.");
 
    int* a = 0;
    *a = 1; // Causing a crash. Bypassing the error dump system.
}
 
int main()
{
    /* Bypasses the pure virtual function called error handler to a user-defined function.
    You only need to put it in at the beginning of the program.*/
    _set_purecall_handler(myPurecallHandler);
    ...
}
// Bypassing "out of the range errors" in the STL to be received by the error dump system.
// Caution!!! The _CrtSetReportHook can enter the function you set using ATLTRACE, so retportType == _CRT_WARN should be ignored.
 
int YourReportHook(int reportType, char *message, int *returnValue)
{
    //Ignore _CRT_WARN or 0.
    if (reprotType != _CRT_WARN)
    {
        int* a = 0;
        *a = 1; // Causing a crash. Bypassing the error dump system.
    }
 
    return 1;
}
 
int main()
{
    /* Bypasses the handler of a C runtime library error to a user-defined function.
    You only need to put it in at the beginning of the program.*/
    _CrtSetReportHook(YourReportHook);
 
    std::vector<int> a;
    a[1] = 0; // Test if an error handler has been bypassed
 
}

- Uninterrupted error dump system(Exception Logger)

ProudNet provides a feature that, when an error occurs in a program, continues to log the location of the error without terminating the program. This is called a uninterrupted error dump system(Exception Logger).

A typical game server will immediately dump the situation and restart the program when it crashes, but in some cases it may be necessary to force the game server to stay up and running without restarting the program.

However, it is dangerous to continue running a server program that has already corrupted its memory state.

Checklist for creating a uninterrupted error dump system

  • You need to install the DbgHelp library (dbghelp.dll).

  • You need to set the C++ Exception compilation option in Visual Studio.

  • Include : DumpCommon.h, MiniDumper.h

  • Link : ProudNetCommon.lib

Production examples

Make sure to initialize the CExceptionLogger instance by calling the CExceptionLogger::Instance().Init() function at the Main Entry Point of the program. Define the path to the dump file by inheriting from the IExceptionLoggerDelegate abstract class and overriding the GetDumpDirectory() member. If it returns a blank (""), the dumpfile is saved in the current folder.

Works on Windows XP and Windows 2003 Server or later versions of the operating system. If you mix the CExceptionLogger class with ATLTRACE() or OutputDebugString(), the load of log entries can degrade program performance.

The source files for this example are located in <install folder>\Sample\SimpleExceptionLogger.

The SimpleExceptionLogger example is not supported since version 1.7.33863.

#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;
        }
    }
}

- Leave a dump file of the current state of the process

It has the ability to leave a dump file of the current state of the process, even if it is not in an error situation, which can be opened along with the debug information file (.pdb) that was generated when the program that it dumped was built, to see what the process was doing at the source level.

This feature allows you to leave a dump of the current state of the process, even in difficult debugging environments. Calling Proud.CMiniDumper.WriteDumpFromHere saves the call stack of all threads in the process at the time of the call to a dump file.

Setting up compilation to use the error dump system
This feature allows you to dump the current state of a process, even in environments where debugging is difficult.