More flexible presubmit handling
This commit is contained in:
parent
967fe4d0fb
commit
bf10d88fb4
@ -382,6 +382,7 @@ class UploadThread: public IThread
|
|||||||
int failed = 0;
|
int failed = 0;
|
||||||
char path[512];
|
char path[512];
|
||||||
char metapath[512];
|
char metapath[512];
|
||||||
|
char presubmitToken[512];
|
||||||
char response[512];
|
char response[512];
|
||||||
|
|
||||||
while (dumps->MoreFiles()) {
|
while (dumps->MoreFiles()) {
|
||||||
@ -405,12 +406,19 @@ class UploadThread: public IThread
|
|||||||
metapath[0] = '\0';
|
metapath[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wantsUpload = PresubmitCrashDump(path);
|
presubmitToken[0] = '\0';
|
||||||
|
PresubmitResponse presubmitResponse = PresubmitCrashDump(path, presubmitToken, sizeof(presubmitToken));
|
||||||
|
|
||||||
if (wantsUpload) {
|
switch (presubmitResponse) {
|
||||||
bool uploaded = UploadCrashDump(path, metapath, response, sizeof(response));
|
case kPRLocalError:
|
||||||
|
failed++;
|
||||||
if (uploaded) {
|
g_pSM->LogError(myself, "Accelerator failed to locally process crash dump");
|
||||||
|
if (log) fprintf(log, "Failed to locally process crash dump");
|
||||||
|
break;
|
||||||
|
case kPRRemoteError:
|
||||||
|
case kPRUploadCrashDumpAndMetadata:
|
||||||
|
case kPRUploadMetadataOnly:
|
||||||
|
if (UploadCrashDump((presubmitResponse == kPRUploadMetadataOnly) ? nullptr : path, metapath, presubmitToken, response, sizeof(response))) {
|
||||||
count++;
|
count++;
|
||||||
g_pSM->LogError(myself, "Accelerator uploaded crash dump: %s", response);
|
g_pSM->LogError(myself, "Accelerator uploaded crash dump: %s", response);
|
||||||
if (log) fprintf(log, "Uploaded crash dump: %s\n", response);
|
if (log) fprintf(log, "Uploaded crash dump: %s\n", response);
|
||||||
@ -419,18 +427,22 @@ class UploadThread: public IThread
|
|||||||
g_pSM->LogError(myself, "Accelerator failed to upload crash dump: %s", response);
|
g_pSM->LogError(myself, "Accelerator failed to upload crash dump: %s", response);
|
||||||
if (log) fprintf(log, "Failed to upload crash dump: %s\n", response);
|
if (log) fprintf(log, "Failed to upload crash dump: %s\n", response);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
case kPRDontUpload:
|
||||||
skip++;
|
skip++;
|
||||||
g_pSM->LogError(myself, "Accelerator crash dump upload skipped by server");
|
g_pSM->LogError(myself, "Accelerator crash dump upload skipped by server");
|
||||||
if (log) fprintf(log, "Skipped due to server request\n");
|
if (log) fprintf(log, "Skipped due to server request\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libsys->PathExists(metapath)) {
|
if (metapath[0]) {
|
||||||
unlink(metapath);
|
unlink(metapath);
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink(path);
|
unlink(path);
|
||||||
|
|
||||||
|
if (log) fflush(log);
|
||||||
|
|
||||||
dumps->NextEntry();
|
dumps->NextEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +461,7 @@ class UploadThread: public IThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined _LINUX
|
#if defined _LINUX
|
||||||
bool UploadSymbolFile(const google_breakpad::CodeModule *module) {
|
bool UploadSymbolFile(const google_breakpad::CodeModule *module, const char *presubmitToken) {
|
||||||
auto debugFile = module->debug_file();
|
auto debugFile = module->debug_file();
|
||||||
if (debugFile[0] != '/') {
|
if (debugFile[0] != '/') {
|
||||||
return false;
|
return false;
|
||||||
@ -487,6 +499,16 @@ class UploadThread: public IThread
|
|||||||
// printf(">>> %s\n", output.c_str());
|
// printf(">>> %s\n", output.c_str());
|
||||||
|
|
||||||
IWebForm *form = webternet->CreateForm();
|
IWebForm *form = webternet->CreateForm();
|
||||||
|
|
||||||
|
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
||||||
|
if (minidumpAccount && minidumpAccount[0]) form->AddString("UserID", minidumpAccount);
|
||||||
|
|
||||||
|
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
||||||
|
|
||||||
|
if (presubmitToken && presubmitToken[0]) {
|
||||||
|
form->AddString("PresubmitToken", presubmitToken);
|
||||||
|
}
|
||||||
|
|
||||||
form->AddString("symbol_file", output.c_str());
|
form->AddString("symbol_file", output.c_str());
|
||||||
|
|
||||||
MemoryDownloader data;
|
MemoryDownloader data;
|
||||||
@ -517,7 +539,7 @@ class UploadThread: public IThread
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool UploadModuleFile(const google_breakpad::CodeModule *module) {
|
bool UploadModuleFile(const google_breakpad::CodeModule *module, const char *presubmitToken) {
|
||||||
const auto &codeFile = module->code_file();
|
const auto &codeFile = module->code_file();
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
@ -531,10 +553,19 @@ class UploadThread: public IThread
|
|||||||
if (log) fprintf(log, "Submitting binary for %s\n", codeFile.c_str());
|
if (log) fprintf(log, "Submitting binary for %s\n", codeFile.c_str());
|
||||||
|
|
||||||
IWebForm *form = webternet->CreateForm();
|
IWebForm *form = webternet->CreateForm();
|
||||||
form->AddString("code_file_path", codeFile.c_str());
|
|
||||||
form->AddString("code_identifier", module->code_identifier().c_str());
|
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
||||||
form->AddString("debug_file_path", module->debug_file().c_str());
|
if (minidumpAccount && minidumpAccount[0]) form->AddString("UserID", minidumpAccount);
|
||||||
|
|
||||||
|
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
||||||
|
|
||||||
|
if (presubmitToken && presubmitToken[0]) {
|
||||||
|
form->AddString("PresubmitToken", presubmitToken);
|
||||||
|
}
|
||||||
|
|
||||||
form->AddString("debug_identifier", module->debug_identifier().c_str());
|
form->AddString("debug_identifier", module->debug_identifier().c_str());
|
||||||
|
form->AddString("code_identifier", module->code_identifier().c_str());
|
||||||
|
|
||||||
form->AddFile("code_file", codeFile.c_str());
|
form->AddFile("code_file", codeFile.c_str());
|
||||||
|
|
||||||
MemoryDownloader data;
|
MemoryDownloader data;
|
||||||
@ -616,7 +647,7 @@ class UploadThread: public IThread
|
|||||||
std::map<std::string, ModuleType, PathComparator> modulePathMap;
|
std::map<std::string, ModuleType, PathComparator> modulePathMap;
|
||||||
bool InitModuleClassificationMap(const std::string &base) {
|
bool InitModuleClassificationMap(const std::string &base) {
|
||||||
if (!modulePathMap.empty()) {
|
if (!modulePathMap.empty()) {
|
||||||
return false;
|
modulePathMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
modulePathMap[base] = kMTGame;
|
modulePathMap[base] = kMTGame;
|
||||||
@ -664,7 +695,15 @@ class UploadThread: public IThread
|
|||||||
return path.substr(0, file_start);
|
return path.substr(0, file_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PresubmitCrashDump(const char *path) {
|
enum PresubmitResponse {
|
||||||
|
kPRLocalError,
|
||||||
|
kPRRemoteError,
|
||||||
|
kPRDontUpload,
|
||||||
|
kPRUploadCrashDumpAndMetadata,
|
||||||
|
kPRUploadMetadataOnly,
|
||||||
|
};
|
||||||
|
|
||||||
|
PresubmitResponse PresubmitCrashDump(const char *path, char *tokenBuffer, size_t tokenBufferLength) {
|
||||||
google_breakpad::ProcessState processState;
|
google_breakpad::ProcessState processState;
|
||||||
google_breakpad::ProcessResult processResult;
|
google_breakpad::ProcessResult processResult;
|
||||||
google_breakpad::MinidumpProcessor minidumpProcessor(nullptr, nullptr);
|
google_breakpad::MinidumpProcessor minidumpProcessor(nullptr, nullptr);
|
||||||
@ -675,7 +714,7 @@ class UploadThread: public IThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (processResult != google_breakpad::PROCESS_OK) {
|
if (processResult != google_breakpad::PROCESS_OK) {
|
||||||
return false;
|
return kPRLocalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
int requestingThread = processState.requesting_thread();
|
int requestingThread = processState.requesting_thread();
|
||||||
@ -685,7 +724,7 @@ class UploadThread: public IThread
|
|||||||
|
|
||||||
const google_breakpad::CallStack *stack = processState.threads()->at(requestingThread);
|
const google_breakpad::CallStack *stack = processState.threads()->at(requestingThread);
|
||||||
if (!stack) {
|
if (!stack) {
|
||||||
return false;
|
return kPRLocalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameCount = stack->frames()->size();
|
int frameCount = stack->frames()->size();
|
||||||
@ -728,9 +767,8 @@ class UploadThread: public IThread
|
|||||||
IWebForm *form = webternet->CreateForm();
|
IWebForm *form = webternet->CreateForm();
|
||||||
|
|
||||||
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
||||||
if (minidumpAccount) form->AddString("UserID", minidumpAccount);
|
if (minidumpAccount && minidumpAccount[0]) form->AddString("UserID", minidumpAccount);
|
||||||
|
|
||||||
form->AddString("GameDirectory", g_pSM->GetGameFolderName());
|
|
||||||
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
||||||
|
|
||||||
form->AddString("CrashSignature", summaryLine.c_str());
|
form->AddString("CrashSignature", summaryLine.c_str());
|
||||||
@ -746,7 +784,7 @@ class UploadThread: public IThread
|
|||||||
|
|
||||||
if (!uploaded) {
|
if (!uploaded) {
|
||||||
if (log) fprintf(log, "Presubmit failed: %s (%d)\n", xfer->LastErrorMessage(), xfer->LastErrorCode());
|
if (log) fprintf(log, "Presubmit failed: %s (%d)\n", xfer->LastErrorMessage(), xfer->LastErrorCode());
|
||||||
return false;
|
return kPRRemoteError;
|
||||||
}
|
}
|
||||||
|
|
||||||
int responseSize = data.GetSize();
|
int responseSize = data.GetSize();
|
||||||
@ -761,28 +799,49 @@ class UploadThread: public IThread
|
|||||||
if (responseSize < 2) {
|
if (responseSize < 2) {
|
||||||
if (log) fprintf(log, "Presubmit response too short\n");
|
if (log) fprintf(log, "Presubmit response too short\n");
|
||||||
delete[] response;
|
delete[] response;
|
||||||
return false;
|
return kPRRemoteError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response[0] == 'E') {
|
if (response[0] == 'E') {
|
||||||
if (log) fprintf(log, "Presubmit error: %s\n", &response[2]);
|
if (log) fprintf(log, "Presubmit error: %s\n", &response[2]);
|
||||||
delete[] response;
|
delete[] response;
|
||||||
return false;
|
return kPRRemoteError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool submitCrash = (response[0] == 'Y');
|
PresubmitResponse presubmitResponse = kPRRemoteError;
|
||||||
|
if (response[0] == 'Y') presubmitResponse = kPRUploadCrashDumpAndMetadata;
|
||||||
|
else if (response[0] == 'N') presubmitResponse = kPRDontUpload;
|
||||||
|
else if (response[0] == 'M') presubmitResponse = kPRUploadMetadataOnly;
|
||||||
|
else return kPRRemoteError;
|
||||||
|
|
||||||
if (response[1] != '|') {
|
if (response[1] != '|') {
|
||||||
if (log) fprintf(log, "Response delimiter missing\n");
|
if (log) fprintf(log, "Response delimiter missing\n");
|
||||||
delete[] response;
|
delete[] response;
|
||||||
return false;
|
return kPRRemoteError;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int responseCount = responseSize - 2;
|
unsigned int responseCount = responseSize - 2;
|
||||||
if (responseCount < moduleCount) {
|
if (responseCount < moduleCount) {
|
||||||
if (log) fprintf(log, "Response module list doesn't match sent list (%d < %d)\n", responseCount, moduleCount);
|
if (log) fprintf(log, "Response module list doesn't match sent list (%d < %d)\n", responseCount, moduleCount);
|
||||||
delete[] response;
|
delete[] response;
|
||||||
return false;
|
return presubmitResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There was a presubmit token included.
|
||||||
|
if (tokenBuffer && responseCount > moduleCount && response[2 + moduleCount] == '|') {
|
||||||
|
int tokenStart = 2 + moduleCount + 1;
|
||||||
|
int tokenEnd = tokenStart;
|
||||||
|
while (tokenEnd < responseSize && response[tokenEnd] != '|') {
|
||||||
|
tokenEnd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tokenLength = tokenEnd - tokenStart;
|
||||||
|
if (tokenLength < tokenBufferLength) {
|
||||||
|
strncpy(tokenBuffer, &response[tokenStart], tokenLength);
|
||||||
|
tokenBuffer[tokenLength] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log) fprintf(log, "Got a presubmit token from server: %s\n", tokenBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mainModule = processState.modules()->GetMainModule();
|
auto mainModule = processState.modules()->GetMainModule();
|
||||||
@ -800,8 +859,13 @@ class UploadThread: public IThread
|
|||||||
bool canBinarySubmit = !binarySubmitOption || (tolower(binarySubmitOption[0]) == 'y' || binarySubmitOption[0] == '1');
|
bool canBinarySubmit = !binarySubmitOption || (tolower(binarySubmitOption[0]) == 'y' || binarySubmitOption[0] == '1');
|
||||||
|
|
||||||
for (unsigned int moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
|
for (unsigned int moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) {
|
||||||
bool submitSymbols = (response[2 + moduleIndex] == 'Y');
|
bool submitSymbols = false;
|
||||||
bool submitBinary = (response[2 + moduleIndex] == 'U');
|
bool submitBinary = (response[2 + moduleIndex] == 'U');
|
||||||
|
|
||||||
|
#if defined _LINUX
|
||||||
|
submitSymbols = (response[2 + moduleIndex] == 'Y');
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!submitSymbols && !submitBinary) {
|
if (!submitSymbols && !submitBinary) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -833,32 +897,38 @@ class UploadThread: public IThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (canBinarySubmit && submitBinary) {
|
if (canBinarySubmit && submitBinary) {
|
||||||
UploadModuleFile(module);
|
UploadModuleFile(module, tokenBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined _LINUX
|
#if defined _LINUX
|
||||||
if (submitSymbols) {
|
if (submitSymbols) {
|
||||||
UploadSymbolFile(module);
|
UploadSymbolFile(module, tokenBuffer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] response;
|
delete[] response;
|
||||||
return submitCrash;
|
return presubmitResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UploadCrashDump(const char *path, const char *metapath, char *response, int maxlen) {
|
bool UploadCrashDump(const char *path, const char *metapath, const char *presubmitToken, char *response, int maxlen) {
|
||||||
IWebForm *form = webternet->CreateForm();
|
IWebForm *form = webternet->CreateForm();
|
||||||
|
|
||||||
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
const char *minidumpAccount = g_pSM->GetCoreConfigValue("MinidumpAccount");
|
||||||
if (minidumpAccount) form->AddString("UserID", minidumpAccount);
|
if (minidumpAccount && minidumpAccount[0]) form->AddString("UserID", minidumpAccount);
|
||||||
|
|
||||||
form->AddString("GameDirectory", g_pSM->GetGameFolderName());
|
form->AddString("GameDirectory", crashGameDirectory);
|
||||||
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
form->AddString("ExtensionVersion", SMEXT_CONF_VERSION);
|
||||||
|
|
||||||
form->AddFile("upload_file_minidump", path);
|
if (presubmitToken && presubmitToken[0]) {
|
||||||
|
form->AddString("PresubmitToken", presubmitToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (metapath[0]) {
|
if (path && path[0]) {
|
||||||
|
form->AddFile("upload_file_minidump", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metapath && metapath[0]) {
|
||||||
form->AddFile("upload_file_metadata", metapath);
|
form->AddFile("upload_file_metadata", metapath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user