1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Compress minidumps with gzip

This commit is contained in:
Michał Janiszewski
2018-10-20 23:54:59 +02:00
parent 98aded2bff
commit 2d95052477
3 changed files with 95 additions and 9 deletions

View File

@@ -29,6 +29,7 @@
# include "../localisation/Language.h"
# include "../rct2/S6Exporter.h"
# include "../scenario/Scenario.h"
# include "../util/Util.h"
# include "platform.h"
# define WSZ(x) L"" x
@@ -42,21 +43,26 @@ const wchar_t* _wszCommitSha1Short = WSZ("");
// OPENRCT2_ARCHITECTURE is required to be defined in version.h
const wchar_t* _wszArchitecture = WSZ(OPENRCT2_ARCHITECTURE);
// Note: uploading gzipped crash dumps manually requires specifying
// 'Content-Encoding: gzip' header in HTTP request, but we cannot do that,
// so just hope the file name with '.gz' suffix is enough.
// For docs on uplading to backtrace.io check
// https://documentation.backtrace.io/product_integration_minidump_breakpad/
static bool UploadMinidump(const wchar_t* dumpPath)
{
std::wstring url(
L"https://submit.backtrace.io/openrct2/f9c5e640d498f15dbe902eab3e822e472af9270d5b0cbdc269cee65a926bf306/minidump");
std::wstring url(L"https://openrct2.sp.backtrace.io:6098/"
L"post?format=minidump&token=f9c5e640d498f15dbe902eab3e822e472af9270d5b0cbdc269cee65a926bf306");
std::map<std::wstring, std::wstring> parameters;
std::map<std::wstring, std::wstring> files;
parameters[L"product_name"] = L"openrct2";
// In case of releases this can be empty
if (wcslen(_wszCommitSha1Short) > 0)
{
parameters[L"version"] = _wszCommitSha1Short;
parameters[L"commit"] = _wszCommitSha1Short;
}
else
{
parameters[L"version"] = String::ToUtf16(gVersionInfoFull);
parameters[L"commit"] = String::ToUtf16(gVersionInfoFull);
}
files[L"upload_file_minidump"] = dumpPath;
std::wstring response;
@@ -89,17 +95,34 @@ static bool OnCrash(
wchar_t saveFilePath[MAX_PATH];
swprintf_s(dumpFilePath, sizeof(dumpFilePath), L"%s/%s.dmp", dumpPath, miniDumpId);
swprintf_s(saveFilePath, sizeof(saveFilePath), L"%s/%s.sv6", dumpPath, miniDumpId);
const wchar_t* minidumpToUpload = dumpFilePath;
// Try to rename the files
wchar_t dumpFilePathNew[MAX_PATH];
swprintf_s(
dumpFilePathNew, sizeof(dumpFilePathNew), L"%s/%s(%s_%s).dmp", dumpPath, miniDumpId, _wszCommitSha1Short,
_wszArchitecture);
wchar_t dumpFilePathGZIP[MAX_PATH];
swprintf_s(dumpFilePathGZIP, sizeof(dumpFilePathGZIP), L"%s.gz", dumpFilePathNew);
FILE* input = _wfopen(dumpFilePath, L"rb");
FILE* dest = _wfopen(dumpFilePathGZIP, L"wb");
if (util_gzip_compress(input, dest))
{
minidumpToUpload = dumpFilePathGZIP;
}
fclose(input);
fclose(dest);
// Try to rename the files
if (_wrename(dumpFilePath, dumpFilePathNew) == 0)
{
std::wcscpy(dumpFilePath, dumpFilePathNew);
}
// Compress to gzip-compatible stream
// Log information to output
wprintf(L"Dump Path: %s\n", dumpPath);
wprintf(L"Dump File Path: %s\n", dumpFilePath);
@@ -123,7 +146,7 @@ static bool OnCrash(
if (gOpenRCT2SilentBreakpad)
{
UploadMinidump(dumpFilePath);
UploadMinidump(minidumpToUpload);
return succeeded;
}
@@ -139,16 +162,19 @@ static bool OnCrash(
int answer = MessageBoxW(nullptr, message, WSZ(OPENRCT2_NAME), MB_YESNO | MB_ICONERROR);
if (answer == IDYES)
{
UploadMinidump(dumpFilePath);
UploadMinidump(minidumpToUpload);
}
HRESULT coInitializeResult = CoInitialize(nullptr);
if (SUCCEEDED(coInitializeResult))
{
LPITEMIDLIST pidl = ILCreateFromPathW(dumpPath);
LPITEMIDLIST files[2];
LPITEMIDLIST files[3];
uint32_t numFiles = 0;
files[numFiles++] = ILCreateFromPathW(dumpFilePath);
// There should be no need to check if this file exists, if it doesn't
// it simply shouldn't get selected.
files[numFiles++] = ILCreateFromPathW(dumpFilePathGZIP);
if (savedGameDumped)
{
files[numFiles++] = ILCreateFromPathW(saveFilePath);

View File

@@ -630,6 +630,64 @@ uint8_t* util_zlib_deflate(const uint8_t* data, size_t data_in_size, size_t* dat
return buffer;
}
// Compress the source to gzip-compatible stream, write to dest.
// Mainly used for compressing the crashdumps
bool util_gzip_compress(FILE* source, FILE* dest)
{
if (source == nullptr || dest == nullptr)
{
return false;
}
int ret, flush;
size_t have;
z_stream strm{};
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
int windowBits = 15;
int GZIP_ENCODING = 16;
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
{
log_error("Failed to initialise stream");
return false;
}
do
{
strm.avail_in = uInt(fread(in, 1, CHUNK, source));
if (ferror(source))
{
deflateEnd(&strm);
log_error("Failed to read data from source");
return false;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
do
{
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush);
if (ret == Z_STREAM_ERROR)
{
log_error("Failed to compress data");
return false;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest))
{
deflateEnd(&strm);
log_error("Failed to write data to destination");
return false;
}
} while (strm.avail_out == 0);
} while (flush != Z_FINISH);
deflateEnd(&strm);
return true;
}
// Type-independent code left as macro to reduce duplicate code.
#define add_clamp_body(value, value_to_add, min_cap, max_cap) \
if ((value_to_add > 0) && (value > (max_cap - (value_to_add)))) \

View File

@@ -12,7 +12,8 @@
#include "../common.h"
#include <time.h>
#include <cstdio>
#include <ctime>
int32_t squaredmetres_to_squaredfeet(int32_t squaredMetres);
int32_t metres_to_feet(int32_t metres);
@@ -56,6 +57,7 @@ uint32_t util_rand();
uint8_t* util_zlib_deflate(const uint8_t* data, size_t data_in_size, size_t* data_out_size);
uint8_t* util_zlib_inflate(uint8_t* data, size_t data_in_size, size_t* data_out_size);
bool util_gzip_compress(FILE* source, FILE* dest);
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add);
int16_t add_clamp_int16_t(int16_t value, int16_t value_to_add);