Crash log: Write log to file and console as it is being generated on Unix
This commit is contained in:
@@ -432,7 +432,7 @@ char *CrashLog::LogCommandLog(char *buffer, const char *last) const
|
|||||||
* @param last The last position in the buffer to write to.
|
* @param last The last position in the buffer to write to.
|
||||||
* @return the position of the \c '\0' character after the buffer.
|
* @return the position of the \c '\0' character after the buffer.
|
||||||
*/
|
*/
|
||||||
char *CrashLog::FillCrashLog(char *buffer, const char *last) const
|
char *CrashLog::FillCrashLog(char *buffer, const char *last)
|
||||||
{
|
{
|
||||||
buffer += seprintf(buffer, last, "*** OpenTTD Crash Report ***\n\n");
|
buffer += seprintf(buffer, last, "*** OpenTTD Crash Report ***\n\n");
|
||||||
|
|
||||||
@@ -452,10 +452,13 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last) const
|
|||||||
}
|
}
|
||||||
buffer += seprintf(buffer, last, "\n");
|
buffer += seprintf(buffer, last, "\n");
|
||||||
|
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
|
|
||||||
buffer = this->LogError(buffer, last, CrashLog::message);
|
buffer = this->LogError(buffer, last, CrashLog::message);
|
||||||
|
|
||||||
#ifdef USE_SCOPE_INFO
|
#ifdef USE_SCOPE_INFO
|
||||||
if (IsMainThread() || IsGameThread()) {
|
if (IsMainThread() || IsGameThread()) {
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
buffer += WriteScopeLog(buffer, last);
|
buffer += WriteScopeLog(buffer, last);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -467,9 +470,13 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer = this->LogOpenTTDVersion(buffer, last);
|
buffer = this->LogOpenTTDVersion(buffer, last);
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
buffer = this->LogStacktrace(buffer, last);
|
buffer = this->LogStacktrace(buffer, last);
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
buffer = this->LogRegisters(buffer, last);
|
buffer = this->LogRegisters(buffer, last);
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
buffer = this->LogOSVersion(buffer, last);
|
buffer = this->LogOSVersion(buffer, last);
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
buffer = this->LogCompiler(buffer, last);
|
buffer = this->LogCompiler(buffer, last);
|
||||||
buffer = this->LogOSVersionDetail(buffer, last);
|
buffer = this->LogOSVersionDetail(buffer, last);
|
||||||
buffer = this->LogConfiguration(buffer, last);
|
buffer = this->LogConfiguration(buffer, last);
|
||||||
@@ -643,7 +650,7 @@ bool CrashLog::WriteCrashLog(const char *buffer, char *filename, const char *fil
|
|||||||
if (file == nullptr) return false;
|
if (file == nullptr) return false;
|
||||||
|
|
||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
size_t written = fwrite(buffer, 1, len, file);
|
size_t written = (len != 0) ? fwrite(buffer, 1, len, file) : 0;
|
||||||
|
|
||||||
if (crashlog_file) {
|
if (crashlog_file) {
|
||||||
*crashlog_file = file;
|
*crashlog_file = file;
|
||||||
@@ -653,6 +660,23 @@ bool CrashLog::WriteCrashLog(const char *buffer, char *filename, const char *fil
|
|||||||
return len == written;
|
return len == written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrashLog::FlushCrashLogBuffer()
|
||||||
|
{
|
||||||
|
if (this->crash_buffer_write == nullptr) return;
|
||||||
|
|
||||||
|
size_t len = strlen(this->crash_buffer_write);
|
||||||
|
if (len == 0) return;
|
||||||
|
|
||||||
|
if (this->crash_file != nullptr) {
|
||||||
|
fwrite(this->crash_buffer_write, 1, len, this->crash_file);
|
||||||
|
fflush(this->crash_file);
|
||||||
|
}
|
||||||
|
fwrite(this->crash_buffer_write, 1, len, stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
this->crash_buffer_write += len;
|
||||||
|
}
|
||||||
|
|
||||||
/* virtual */ int CrashLog::WriteCrashDump(char *filename, const char *filename_last) const
|
/* virtual */ int CrashLog::WriteCrashDump(char *filename, const char *filename_last) const
|
||||||
{
|
{
|
||||||
/* Stub implementation; not all OSes support this. */
|
/* Stub implementation; not all OSes support this. */
|
||||||
@@ -771,18 +795,25 @@ bool CrashLog::MakeCrashLog(char *buffer, const char *last)
|
|||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
printf("Crash encountered, generating crash log...\n");
|
printf("Crash encountered, generating crash log...\n");
|
||||||
this->FillCrashLog(buffer, last);
|
|
||||||
printf("%s\n", buffer);
|
|
||||||
printf("Crash log generated.\n\n");
|
|
||||||
|
|
||||||
printf("Writing crash log to disk...\n");
|
printf("Writing crash log to disk...\n");
|
||||||
bool bret = this->WriteCrashLog(buffer, filename, lastof(filename), this->name_buffer);
|
bool bret = this->WriteCrashLog("", filename, lastof(filename), this->name_buffer, &(this->crash_file));
|
||||||
if (bret) {
|
if (bret) {
|
||||||
printf("Crash log written to %s. Please add this file to any bug reports.\n\n", filename);
|
printf("Crash log written to %s. Please add this file to any bug reports.\n\n", filename);
|
||||||
} else {
|
} else {
|
||||||
printf("Writing crash log failed. Please attach the output above to any bug reports.\n\n");
|
printf("Writing crash log failed. Please attach the output above to any bug reports.\n\n");
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
this->crash_buffer_write = buffer;
|
||||||
|
|
||||||
|
this->FillCrashLog(buffer, last);
|
||||||
|
this->FlushCrashLogBuffer();
|
||||||
|
if (this->crash_file != nullptr) {
|
||||||
|
FioFCloseFile(this->crash_file);
|
||||||
|
this->crash_file = nullptr;
|
||||||
|
}
|
||||||
|
printf("Crash log generated.\n\n");
|
||||||
|
|
||||||
|
|
||||||
/* Don't mention writing crash dumps because not all platforms support it. */
|
/* Don't mention writing crash dumps because not all platforms support it. */
|
||||||
int dret = this->WriteCrashDump(filename, lastof(filename));
|
int dret = this->WriteCrashDump(filename, lastof(filename));
|
||||||
|
@@ -131,11 +131,14 @@ protected:
|
|||||||
public:
|
public:
|
||||||
/** Buffer for the filename name prefix */
|
/** Buffer for the filename name prefix */
|
||||||
char name_buffer[64];
|
char name_buffer[64];
|
||||||
|
FILE *crash_file = nullptr;
|
||||||
|
const char *crash_buffer_write = nullptr;
|
||||||
|
|
||||||
/** Stub destructor to silence some compilers. */
|
/** Stub destructor to silence some compilers. */
|
||||||
virtual ~CrashLog() {}
|
virtual ~CrashLog() {}
|
||||||
|
|
||||||
char *FillCrashLog(char *buffer, const char *last) const;
|
char *FillCrashLog(char *buffer, const char *last);
|
||||||
|
void FlushCrashLogBuffer();
|
||||||
char *FillDesyncCrashLog(char *buffer, const char *last, const DesyncExtraInfo &info) const;
|
char *FillDesyncCrashLog(char *buffer, const char *last, const DesyncExtraInfo &info) const;
|
||||||
char *FillInconsistencyLog(char *buffer, const char *last, const InconsistencyExtraInfo &info) const;
|
char *FillInconsistencyLog(char *buffer, const char *last, const InconsistencyExtraInfo &info) const;
|
||||||
char *FillVersionInfoLog(char *buffer, const char *last) const;
|
char *FillVersionInfoLog(char *buffer, const char *last) const;
|
||||||
|
Reference in New Issue
Block a user