]> git.mxchange.org Git - flightgear.git/blob - src/Main/bootstrap.cxx
Code cleanups, code updates and fix at least on (possible) devide-by-zero
[flightgear.git] / src / Main / bootstrap.cxx
1 // bootstrap.cxx -- bootstrap routines: main()
2 //
3 // Written by Curtis Olson, started May 1997.
4 //
5 // Copyright (C) 1997 - 2002  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
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.
11 //
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.
16 //
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.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #ifdef HAVE_WINDOWS_H
29 #include <windows.h>
30 #endif
31
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
35
36   #ifndef _GNU_SOURCE
37     #define _GNU_SOURCE
38   #endif
39
40   #include <fenv.h>
41 #endif
42
43 #ifndef _WIN32
44 #  include <unistd.h> // for gethostname()
45 #endif
46
47 #include <errno.h>
48 #include <signal.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <cstring>
52 #include <iostream>
53 #include <locale.h>
54
55 #include <simgear/compiler.h>
56 #include <simgear/structure/exception.hxx>
57
58 #include <osg/Texture>
59 #include <osg/BufferObject>
60
61 #include <Viewer/fgviewer.hxx>
62 #include "main.hxx"
63 #include <Include/version.h>
64 #include <Main/globals.hxx>
65 #include <Main/options.hxx>
66 #include <Main/fg_props.hxx>
67 #include <GUI/MessageBox.hxx>
68
69 #include "fg_os.hxx"
70
71 #if defined(HAVE_CRASHRPT)
72         #include <CrashRpt.h>
73
74 bool global_crashRptEnabled = false;
75
76 #endif
77
78 using std::cerr;
79 using std::endl;
80
81 std::string homedir;
82 std::string hostname;
83
84 // forward declaration.
85 void fgExitCleanup();
86
87 static void initFPE(bool enableExceptions);
88
89 #if defined(__linux__)
90
91 static void handleFPE(int);
92 static void
93 initFPE (bool fpeAbort)
94 {
95     if (fpeAbort) {
96         int except = fegetexcept();
97         feenableexcept(except | FE_DIVBYZERO | FE_INVALID);
98     } else {
99         signal(SIGFPE, handleFPE);
100     }
101 }
102
103 static void handleFPE(int)
104 {
105     feclearexcept(FE_ALL_EXCEPT);
106     SG_LOG(SG_GENERAL, SG_ALERT, "Floating point interrupt (SIGFPE)");
107     signal(SIGFPE, handleFPE);
108 }
109 #elif defined (SG_WINDOWS)
110
111 static void initFPE(bool fpeAbort)
112 {
113 // Enable floating-point exceptions for Windows
114     if (fpeAbort) {
115         // set following link for what this does (note it does set SSE
116         // flags too, it's not just for the x87 FPU)
117         // http://msdn.microsoft.com/en-us/library/e9b52ceh.aspx
118         _control87( _EM_INEXACT, _MCW_EM );
119     }
120 }
121
122 #else
123 static void initFPE(bool)
124 {
125     // Ignore floating-point exceptions on FreeBSD, OS-X, other Unices
126     signal(SIGFPE, SIG_IGN);
127 }
128 #endif
129
130 #if defined(SG_WINDOWS)
131 int main ( int argc, char **argv );
132 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
133                              LPSTR lpCmdLine, int nCmdShow) {
134
135   main( __argc, __argv );
136 }
137 #endif
138
139 static void fg_terminate()
140 {
141     flightgear::fatalMessageBox("Fatal exception", "Uncaught exception on some thread");
142 }
143
144 int _bootstrap_OSInit;
145
146 // Main entry point; catch any exceptions that have made it this far.
147 int main ( int argc, char **argv )
148 {
149 #if defined(SG_WINDOWS)
150   // Don't show blocking "no disk in drive" error messages on Windows 7,
151   // silently return errors to application instead.
152   // See Microsoft MSDN #ms680621: "GUI apps should specify SEM_NOOPENFILEERRORBOX"
153   SetErrorMode(SEM_NOOPENFILEERRORBOX);
154
155   hostname = ::getenv( "COMPUTERNAME" );
156 #else
157   // Unix(alike) systems
158   char _hostname[256];
159   gethostname(_hostname, 256);
160   hostname = _hostname;
161     
162   signal(SIGPIPE, SIG_IGN);
163 #endif
164
165     _bootstrap_OSInit = 0;
166
167 #if defined(HAVE_CRASHRPT)
168         // Define CrashRpt configuration parameters
169         CR_INSTALL_INFO info;  
170         memset(&info, 0, sizeof(CR_INSTALL_INFO));  
171         info.cb = sizeof(CR_INSTALL_INFO);    
172         info.pszAppName = "FlightGear";
173         info.pszAppVersion = FLIGHTGEAR_VERSION;
174         info.pszEmailSubject = "FlightGear " FLIGHTGEAR_VERSION " crash report";
175         info.pszEmailTo = "fgcrash@goneabitbursar.com";
176         info.pszUrl = "http://fgfs.goneabitbursar.com/crashreporter/crashrpt.php";
177         info.uPriorities[CR_HTTP] = 3; 
178         info.uPriorities[CR_SMTP] = 2;  
179         info.uPriorities[CR_SMAPI] = 1;
180
181         // Install all available exception handlers
182         info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;
183   
184         // Restart the app on crash 
185         info.dwFlags |= CR_INST_SEND_QUEUED_REPORTS; 
186
187         // automatically install handlers for all threads
188         info.dwFlags |= CR_INST_AUTO_THREAD_HANDLERS;
189
190         // Define the Privacy Policy URL 
191         info.pszPrivacyPolicyURL = "http://flightgear.org/crash-privacypolicy.html"; 
192   
193         // Install crash reporting
194         int nResult = crInstall(&info);    
195         if(nResult!=0) {
196                 char buf[1024];
197                 crGetLastErrorMsg(buf, 1024);
198                 flightgear::modalMessageBox("CrashRpt setup failed", 
199                         "Failed to setup crash-reporting engine, check the installation is not damaged.",
200                         buf);
201         } else {
202                 global_crashRptEnabled = true;
203
204                 crAddProperty("hudson-build-id", HUDSON_BUILD_ID);
205                 char buf[16];
206                 ::snprintf(buf, 16, "%d", HUDSON_BUILD_NUMBER);
207                 crAddProperty("hudson-build-number", buf);
208         crAddProperty("git-revision", REVISION);
209 #if defined(FG_NIGHTLY)
210         crAddProperty("nightly-build", "true");
211 #endif
212         }
213 #endif
214
215     initFPE(flightgear::Options::checkForArg(argc, argv, "enable-fpe"));
216
217     // pick up all user locale settings, but force C locale for numerical/sorting
218     // conversions because we have lots of code which assumes standard
219     // formatting
220     setlocale(LC_ALL, "");
221     setlocale(LC_NUMERIC, "C");
222     setlocale(LC_COLLATE, "C");
223
224     bool fgviewer = flightgear::Options::checkForArg(argc, argv, "fgviewer");
225     try {
226         // http://code.google.com/p/flightgear-bugs/issues/detail?id=1231
227         // ensure sglog is inited before atexit() is registered, so logging
228         // is possible inside fgExitCleanup
229         sglog();
230
231
232 #if (OPENSCENEGRAPH_MAJOR_VERSION == 3) && (OPENSCENEGRAPH_MINOR_VERSION < 5)
233         // similar to above, ensure some static maps inside OSG exist before
234         // we register our at-exit handler, otherwise the statics are gone
235         // when fg_terminate runs, which causes crashes.
236         osg::Texture::getTextureObjectManager(0);
237         osg::GLBufferObjectManager::getGLBufferObjectManager(0);
238 #endif
239         std::set_terminate(fg_terminate);
240         atexit(fgExitCleanup);
241         if (fgviewer)
242             fgviewerMain(argc, argv);
243         else
244             fgMainInit(argc, argv);
245            
246     } catch (const sg_throwable &t) {
247         std::string info;
248         if (std::strlen(t.getOrigin()) != 0)
249             info = std::string("received from ") + t.getOrigin();
250         flightgear::fatalMessageBox("Fatal exception", t.getFormattedMessage(), info);
251
252     } catch (const std::exception &e ) {
253         flightgear::fatalMessageBox("Fatal exception", e.what());
254     } catch (const std::string &s) {
255         flightgear::fatalMessageBox("Fatal exception", s);
256     } catch (const char *s) {
257         std::cerr << "Fatal error (const char*): " << s << std::endl;
258
259     } catch (...) {
260         std::cerr << "Unknown exception in the main loop. Aborting..." << std::endl;
261         if (errno)
262             perror("Possible cause");
263     }
264
265 #if defined(HAVE_CRASHRPT)
266         crUninstall();
267 #endif
268
269     return 0;
270 }
271
272 // do some clean up on exit.  Specifically we want to delete the sound-manager,
273 // so OpenAL device and context are released cleanly
274 void fgExitCleanup() {
275
276     if (_bootstrap_OSInit != 0) {
277         fgSetMouseCursor(MOUSE_CURSOR_POINTER);
278
279         fgOSCloseWindow();
280     }
281     
282     // on the common exit path globals is already deleted, and NULL,
283     // so this only happens on error paths.
284     delete globals;
285 }
286