52#include <simgear/compiler.h>
53#include <simgear/structure/exception.hxx>
54#include <simgear/scene/tgdb/GroundLightManager.hxx>
56#include <osg/BufferObject>
59#include <osgText/Font>
86static void initFPE(
bool enableExceptions);
90static void handleFPE(
int);
95 int except = fegetexcept();
96 feenableexcept(except | FE_DIVBYZERO | FE_INVALID);
98 signal(SIGFPE, handleFPE);
102static void handleFPE(
int)
104 feclearexcept(FE_ALL_EXCEPT);
105 SG_LOG(SG_GENERAL, SG_ALERT,
"Floating point interrupt (SIGFPE)");
106 signal(SIGFPE, handleFPE);
108#elif defined (SG_WINDOWS)
110static void initFPE(
bool fpeAbort)
117 _control87( _EM_INEXACT, _MCW_EM );
125 signal(SIGFPE, SIG_IGN);
129#if defined(SG_WINDOWS)
130int main (
int argc,
char **argv );
131int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
132 LPSTR lpCmdLine,
int nCmdShow)
136 LPWSTR* wideArgs = CommandLineToArgvW(GetCommandLineW(), &numArgs);
138 std::vector<char*> utf8Args;
139 utf8Args.resize(numArgs);
141 for (
int a = 0; a < numArgs; ++a) {
142 const auto s = simgear::strutils::convertWStringToUtf8(wideArgs[a]);
144 utf8Args[a] = strdup(s.c_str());
147 main(numArgs, utf8Args.data());
152bool checkUniversalCRTVersion()
155 VS_FIXEDFILEINFO *pFileInfo = NULL;
156 UINT puLenFileInfo = 0;
159 dwSize = GetFileVersionInfoSizeA(
"ucrtbase.dll", NULL);
164 std::vector<BYTE> versionInfo;
165 versionInfo.resize(dwSize);
167 if (!GetFileVersionInfoA(
"ucrtbase.dll", 0, dwSize, versionInfo.data())) {
171 if (!VerQueryValue(versionInfo.data(), TEXT(
"\\"), (LPVOID*)&pFileInfo, &puLenFileInfo)) {
175 const WORD majorVersion = pFileInfo->dwFileVersionMS >> 16;
176 const WORD minorVersion = pFileInfo->dwFileVersionMS & 0xffff;
177 const WORD buildVersion = pFileInfo->dwFileVersionLS >> 16;
178 const WORD releaseVersion = pFileInfo->dwFileVersionLS & 0xffff;
184 return (buildVersion > 10586);
192void segfault_handler(
int signo) {
194 fprintf(stderr,
"Error: caught signal %d:\n", signo);
199 size = backtrace(array, 128);
201 char** list = backtrace_symbols(array, size);
203 char* fname = (
char*)malloc(fnlen);
205 for (
size_t i=1;
i<size;
i++) {
206 char *begin = 0, *offset = 0, *end = 0;
207 for (
char *
p = list[
i]; *
p; ++
p) {
208 if (*
p ==
'(') begin =
p;
209 else if (*
p ==
'+') offset =
p;
210 else if (*
p ==
')' && offset) {
216 if (begin && offset && end && begin<offset) {
217 *begin++ =
'\0'; *offset++ =
'\0'; *end =
'\0';
220 char* ret = abi::__cxa_demangle(begin, fname, &fnlen, &
status);
223 fprintf(stderr,
" %s : %s+%s\n", list[
i], fname, offset);
226 fprintf(stderr,
" %s : %s()+%s\n", list[
i], begin, offset);
229 fprintf(stderr,
" %s\n", list[
i]);
243 cerr <<
"Running FlightGear's terminate handler. The program is going to "
244 "exit due to a fatal error condition, sorry." << std::endl;
250# if defined(SG_WINDOWS)
252# define get_cpuid(a,b) __cpuid(a,b)
255# define get_cpuid(a,b) __cpuid(b,a[0],a[1],a[2],a[3])
257# define CPUID_GETFEATURES 1
258# define CPUID_FEAT_EDX_SSE2 (1 << 26)
261 static int regs[4] = {0,0,0,0};
262 get_cpuid(regs, CPUID_GETFEATURES);
263 return (regs[3] & CPUID_FEAT_EDX_SSE2);
272int main (
int argc,
char **argv )
284 "SSE2 support not detected, but this version of FlightGear requires "
285 "SSE2 hardware support.");
289#if defined(SG_WINDOWS)
293 SetErrorMode(SEM_NOOPENFILEERRORBOX);
295 hostname = ::getenv(
"COMPUTERNAME" );
297 if (!checkUniversalCRTVersion()) {
300 "The Microsoft Universal CRT on this computer is too old to run FlightGear. "
301 "Please use Windows Update to install a more recent Universal CRT version.");
306 gethostname(_hostname, 256);
308 signal(SIGPIPE, SIG_IGN);
313#if defined(HAVE_SENTRY)
324#if !defined(SG_WINDOWS) && !defined(NDEBUG) && !defined(__OpenBSD__)
326 signal(SIGSEGV, segfault_handler);
335 setlocale(LC_ALL,
"");
336 setlocale(LC_NUMERIC,
"C");
337 setlocale(LC_COLLATE,
"C");
344 int exitStatus = EXIT_FAILURE;
360 }
catch (
const sg_throwable &t) {
362 if (std::strlen(t.getOrigin()) != 0)
363 info = std::string(
"received from ") + t.getOrigin();
365 "Fatal exception", t.getFormattedMessage(), info);
366 }
catch (
const std::bad_alloc&) {
368 "FlightGear ran out of memory and must exit.",
"Consider adjusting your settings or closing other applications.");
369 }
catch (
const std::exception &e ) {
371 }
catch (
const std::string &s) {
375 }
catch (
const char *s) {
376 std::cerr <<
"Fatal error (const char*): " << s << std::endl;
379 std::cerr <<
"Unknown exception in the main loop. Aborting..." << std::endl;
381 perror(
"Possible cause");
412 simgear::shutdownLogging();
static void initFPE(bool enableExceptions)
static void fg_terminate()
static bool checkForArgEnable(int argc, char *argv[], const std::string &checkArg)
Return true when user explicitly enabled boolean option, otherwise false.
static bool checkForArg(int argc, char *argv[], const char *arg)
Check if the arguments array contains a particular string (with a '–' or '-' prefix).
static bool checkForArgDisable(int argc, char *argv[], const std::string &checkArg)
Return true when user explicitly disabled boolean option by set false value.
int fgviewerMain(int argc, char **argv)
int fgMainInit(int argc, char **argv)
MessageBoxResult fatalMessageBoxWithoutExit(const std::string &caption, const std::string &msg, const std::string &moreText, bool reportToSentry)
void addSentryBreadcrumb(const std::string &, const std::string &)
void sentryReportException(const std::string &, const std::string &)
void fatalMessageBoxThenExit(const std::string &caption, const std::string &msg, const std::string &moreText, int exitStatus, bool reportToSentry)
void setHeadlessMode(bool headless)