1 // bootstrap.cxx -- bootstrap routines: main()
3 // Written by Curtis Olson, started May 1997.
5 // Copyright (C) 1997 - 2002 Curtis L. Olson - http://www.flightgear.org/~curt
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #if defined(__linux__)
33 // set link for setting _GNU_SOURCE before including fenv.h
34 // http://man7.org/linux/man-pages/man3/fenv.3.html
44 # include <unistd.h> // for gethostname()
54 #include <simgear/compiler.h>
55 #include <simgear/structure/exception.hxx>
57 #include <osg/Texture>
58 #include <osg/BufferObject>
60 #include <Viewer/fgviewer.hxx>
62 #include <Include/version.h>
63 #include <Main/globals.hxx>
64 #include <Main/options.hxx>
65 #include <Main/fg_props.hxx>
66 #include <GUI/MessageBox.hxx>
70 #if defined(HAVE_CRASHRPT)
73 bool global_crashRptEnabled = false;
83 // forward declaration.
86 static void initFPE(bool enableExceptions);
88 #if defined(__linux__)
90 static void handleFPE(int);
92 initFPE (bool fpeAbort)
95 int except = fegetexcept();
96 feenableexcept(except | FE_DIVBYZERO | FE_INVALID);
98 signal(SIGFPE, handleFPE);
102 static 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)
110 static void initFPE(bool fpeAbort)
112 // Enable floating-point exceptions for Windows
114 // set following link for what this does (note it does set SSE
115 // flags too, it's not just for the x87 FPU)
116 // http://msdn.microsoft.com/en-us/library/e9b52ceh.aspx
117 _control87( _EM_INEXACT, _MCW_EM );
122 static void initFPE(bool)
124 // Ignore floating-point exceptions on FreeBSD, OS-X, other Unices
125 signal(SIGFPE, SIG_IGN);
129 #if defined(SG_WINDOWS)
130 int main ( int argc, char **argv );
131 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
132 LPSTR lpCmdLine, int nCmdShow) {
134 main( __argc, __argv );
138 static void fg_terminate()
140 flightgear::fatalMessageBox("Fatal exception", "Uncaught exception on some thread");
143 int _bootstrap_OSInit;
145 // Main entry point; catch any exceptions that have made it this far.
146 int main ( int argc, char **argv )
148 #if defined(SG_WINDOWS)
149 // Don't show blocking "no disk in drive" error messages on Windows 7,
150 // silently return errors to application instead.
151 // See Microsoft MSDN #ms680621: "GUI apps should specify SEM_NOOPENFILEERRORBOX"
152 SetErrorMode(SEM_NOOPENFILEERRORBOX);
154 hostname = ::getenv( "COMPUTERNAME" );
156 // Unix(alike) systems
158 gethostname(_hostname, 256);
159 hostname = _hostname;
161 signal(SIGPIPE, SIG_IGN);
164 _bootstrap_OSInit = 0;
166 #if defined(HAVE_CRASHRPT)
167 // Define CrashRpt configuration parameters
168 CR_INSTALL_INFO info;
169 memset(&info, 0, sizeof(CR_INSTALL_INFO));
170 info.cb = sizeof(CR_INSTALL_INFO);
171 info.pszAppName = "FlightGear";
172 info.pszAppVersion = FLIGHTGEAR_VERSION;
173 info.pszEmailSubject = "FlightGear " FLIGHTGEAR_VERSION " crash report";
174 info.pszEmailTo = "fgcrash@goneabitbursar.com";
175 info.pszUrl = "http://fgfs.goneabitbursar.com/crashreporter/crashrpt.php";
176 info.uPriorities[CR_HTTP] = 3;
177 info.uPriorities[CR_SMTP] = 2;
178 info.uPriorities[CR_SMAPI] = 1;
180 // Install all available exception handlers
181 info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;
183 // Restart the app on crash
184 info.dwFlags |= CR_INST_SEND_QUEUED_REPORTS;
186 // automatically install handlers for all threads
187 info.dwFlags |= CR_INST_AUTO_THREAD_HANDLERS;
189 // Define the Privacy Policy URL
190 info.pszPrivacyPolicyURL = "http://flightgear.org/crash-privacypolicy.html";
192 // Install crash reporting
193 int nResult = crInstall(&info);
196 crGetLastErrorMsg(buf, 1024);
197 flightgear::modalMessageBox("CrashRpt setup failed",
198 "Failed to setup crash-reporting engine, check the installation is not damaged.",
201 global_crashRptEnabled = true;
203 crAddProperty("hudson-build-id", HUDSON_BUILD_ID);
205 ::snprintf(buf, 16, "%d", HUDSON_BUILD_NUMBER);
206 crAddProperty("hudson-build-number", buf);
207 crAddProperty("git-revision", REVISION);
208 #if defined(FG_NIGHTLY)
209 crAddProperty("nightly-build", "true");
214 initFPE(flightgear::Options::checkForArg(argc, argv, "enable-fpe"));
216 bool fgviewer = flightgear::Options::checkForArg(argc, argv, "fgviewer");
218 // http://code.google.com/p/flightgear-bugs/issues/detail?id=1231
219 // ensure sglog is inited before atexit() is registered, so logging
220 // is possible inside fgExitCleanup
224 #if (OPENSCENEGRAPH_MAJOR_VERSION == 3) && (OPENSCENEGRAPH_MINOR_VERSION < 5)
225 // similar to above, ensure some static maps inside OSG exist before
226 // we register our at-exit handler, otherwise the statics are gone
227 // when fg_terminate runs, which causes crashes.
228 osg::Texture::getTextureObjectManager(0);
229 osg::GLBufferObjectManager::getGLBufferObjectManager(0);
231 std::set_terminate(fg_terminate);
232 atexit(fgExitCleanup);
234 fgviewerMain(argc, argv);
236 fgMainInit(argc, argv);
238 } catch (const sg_throwable &t) {
240 if (std::strlen(t.getOrigin()) != 0)
241 info = std::string("received from ") + t.getOrigin();
242 flightgear::fatalMessageBox("Fatal exception", t.getFormattedMessage(), info);
244 } catch (const std::exception &e ) {
245 flightgear::fatalMessageBox("Fatal exception", e.what());
246 } catch (const std::string &s) {
247 flightgear::fatalMessageBox("Fatal exception", s);
248 } catch (const char *s) {
249 std::cerr << "Fatal error (const char*): " << s << std::endl;
252 std::cerr << "Unknown exception in the main loop. Aborting..." << std::endl;
254 perror("Possible cause");
257 #if defined(HAVE_CRASHRPT)
264 // do some clean up on exit. Specifically we want to delete the sound-manager,
265 // so OpenAL device and context are released cleanly
266 void fgExitCleanup() {
268 if (_bootstrap_OSInit != 0) {
269 fgSetMouseCursor(MOUSE_CURSOR_POINTER);
274 // on the common exit path globals is already deleted, and NULL,
275 // so this only happens on error paths.