forked from opentibia-xx/otserv
/
exception.cpp
147 lines (117 loc) · 3.85 KB
/
exception.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
//////////////////////////////////////////////////////////////////////
// Exception Handler class
//////////////////////////////////////////////////////////////////////
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"
#include <boost/thread.hpp>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <map>
#include "exception.h"
#include "configmanager.h"
extern ConfigManager g_config;
#ifdef __WINDOWS__
int ExceptionHandler::ref_counter = 0;
#endif
ExceptionHandler::ExceptionHandler()
{
isInstalled = false;
}
ExceptionHandler::~ExceptionHandler()
{
if(isInstalled){
RemoveHandler();
}
}
bool ExceptionHandler::InstallHandler()
{
#ifdef __WINDOWS__
++ref_counter;
if(ref_counter == 1){
SetUnhandledExceptionFilter(ExceptionHandler::MiniDumpExceptionHandler);
}
#endif
isInstalled = true;
return true;
}
bool ExceptionHandler::RemoveHandler()
{
if(!isInstalled){
return false;
}
#ifdef __WINDOWS__
--ref_counter;
if(ref_counter == 0){
SetUnhandledExceptionFilter(NULL);
}
#endif
isInstalled = false;
return true;
}
#ifdef __WINDOWS__
long ExceptionHandler::MiniDumpExceptionHandler(EXCEPTION_POINTERS* exceptionPointers /*= NULL*/)
{
// Alerts the user about what is happening
std::cout << "Unhandled exception. Generating minidump..." << std::endl;
// Get system time
SYSTEMTIME systemTime;
GetSystemTime(&systemTime);
// Format file name
// "otserv_DD-MM-YYYY_HH-MM-SS.mdmp"
char fileName[64] = {"\0"};
sprintf(fileName, "otserv_%02u-%02u-%04u_%02u-%02u-%02u.mdmp",
systemTime.wDay, systemTime.wMonth, systemTime.wYear,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
// Create the dump file
HANDLE hFile = CreateFileA(fileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// If we cannot create the file, then we cannot dump the memory
if(!hFile || hFile == INVALID_HANDLE_VALUE){
std::cout << "Cannot create dump file. Error: " << GetLastError() << std::endl;
return EXCEPTION_CONTINUE_SEARCH;
}
// Collect the exception information
MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
exceptionInformation.ClientPointers = FALSE;
exceptionInformation.ExceptionPointers = exceptionPointers;
exceptionInformation.ThreadId = GetCurrentThreadId();
// Get the process and it's Id
HANDLE hProcess = GetCurrentProcess();
DWORD ProcessId = GetProcessId(hProcess);
// Dump flags
MINIDUMP_TYPE flags = (MINIDUMP_TYPE)(MiniDumpNormal);
// Write dump to file
BOOL dumpResult = MiniDumpWriteDump(hProcess, ProcessId, hFile, flags,
&exceptionInformation, NULL, NULL);
// Delete the dump file if we cannot generate the crash trace
if(!dumpResult){
std::cout << "Cannot generate minidump. Error: " << GetLastError() << std::endl;
//Close file and delete it
CloseHandle(hFile);
DeleteFileA(fileName);
return EXCEPTION_CONTINUE_SEARCH;
}
// Close dump file
CloseHandle(hFile);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif