diff --git a/src/crashlog.cpp b/src/crashlog.cpp index a0ec4d26fb..ead0d96f3e 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -81,6 +81,13 @@ char *CrashLog::LogCompiler(char *buffer, const char *last) const return buffer; } +#ifdef USE_SCOPE_INFO +/* virtual */ char *CrashLog::LogScopeInfo(char *buffer, const char *last) const +{ + return buffer + WriteScopeLog(buffer, last); +} +#endif + /** * Writes OpenTTD's version to the buffer. * @param buffer The begin where to write at. diff --git a/src/crashlog.h b/src/crashlog.h index 6f7fb3c215..7894dea0ad 100644 --- a/src/crashlog.h +++ b/src/crashlog.h @@ -80,6 +80,16 @@ protected: */ virtual char *LogModules(char *buffer, const char *last) const; +#ifdef USE_SCOPE_INFO + /** + * Writes the scope info log to the buffer. + * This may only be called when IsMainThread() returns true + * @param buffer The begin where to write at. + * @param last The last position in the buffer to write to. + * @return the position of the \c '\0' character after the buffer. + */ + virtual char *LogScopeInfo(char *buffer, const char *last) const; +#endif char *LogOpenTTDVersion(char *buffer, const char *last) const; char *LogConfiguration(char *buffer, const char *last) const; diff --git a/src/os/unix/crashlog_unix.cpp b/src/os/unix/crashlog_unix.cpp index 7d04b641cb..60c8208785 100644 --- a/src/os/unix/crashlog_unix.cpp +++ b/src/os/unix/crashlog_unix.cpp @@ -251,6 +251,38 @@ class CrashLogUnix : public CrashLog { #endif return buffer + seprintf(buffer, last, "\n"); } + +#if defined(USE_SCOPE_INFO) && defined(__GLIBC__) + /** + * This is a wrapper around the generic LogScopeInfo function which sets + * up a signal handler to catch any SIGSEGVs which may occur due to invalid data + */ + /* virtual */ char *LogScopeInfo(char *buffer, const char *last) const + { + logStacktraceSavedBuffer = buffer; + + if (setjmp(logStacktraceJmpBuf) != 0) { + buffer = logStacktraceSavedBuffer; + buffer += seprintf(buffer, last, "\nSomething went seriously wrong when attempting to dump the scope info (SIGSEGV in signal handler).\n"); + buffer += seprintf(buffer, last, "This is probably due to an invalid pointer or other corrupt data.\n\n"); + return buffer; + } + + signal(SIGSEGV, LogStacktraceSigSegvHandler); + sigset_t sigs; + sigset_t oldsigs; + sigemptyset(&sigs); + sigaddset(&sigs, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &sigs, &oldsigs); + + buffer = this->CrashLog::LogScopeInfo(buffer, last); + + signal(SIGSEGV, SIG_DFL); + sigprocmask(SIG_SETMASK, &oldsigs, NULL); + return buffer; + } +#endif + public: /** * A crash log is always generated by signal. diff --git a/src/scope_info.cpp b/src/scope_info.cpp index fa7a14d628..19fa67c905 100644 --- a/src/scope_info.cpp +++ b/src/scope_info.cpp @@ -56,10 +56,18 @@ const char *scope_dumper::VehicleInfo(const Vehicle *v) const char *last = lastof(this->buffer); if (v) { b += seprintf(b, last, "veh: %u: (", v->index); + if (Vehicle::GetIfValid(v->index) != v) { + b += seprintf(b, last, "INVALID PTR: %p)", v); + return this->buffer; + } SetDParam(0, v->index); b = GetString(b, STR_VEHICLE_NAME, last); if (v->First() && v->First() != v) { b += seprintf(b, last, "), front: %u: (", v->First()->index); + if (Vehicle::GetIfValid(v->First()->index) != v->First()) { + b += seprintf(b, last, "INVALID PTR: %p)", v->First()); + return this->buffer; + } SetDParam(0, v->First()->index); b = GetString(b, STR_VEHICLE_NAME, last); }