]> git.tdb.fi Git - libs/core.git/blob - source/core/application.cpp
Redesign uncaught exception handling to allow external reporters
[libs/core.git] / source / core / application.cpp
1 #include <typeinfo>
2 #include <signal.h>
3 #include <msp/debug/demangle.h>
4 #include <msp/debug/errorreporter.h>
5 #include <msp/io/print.h>
6 #include "application.h"
7 #include "getopt.h"
8
9 using namespace std;
10
11 namespace Msp {
12
13 Application *Application::app_ = 0;
14 Application::Starter *Application::starter_ = 0;
15 void *Application::data_ = 0;
16
17 Application::Application():
18         exit_code(0)
19 { }
20
21 int Application::run(int argc, char **argv, void *data)
22 {
23         static bool called = false;
24         if(called)
25         {
26                 IO::cerr.write("Trying to call Application::run_app twice!\n");
27                 return 125;
28         }
29         called = true;
30
31         if(!starter_)
32         {
33                 IO::cerr.write("Trying to run with no RegisteredApplication class!\n");
34                 return 126;
35         }
36
37         data_ = data;
38
39         try
40         {
41                 try
42                 {
43                         app_ = starter_->create_app(argc, argv);
44                 }
45                 catch(const usage_error &e)
46                 {
47                         IO::print(IO::cerr, "%s\n%s\n", e.what(), e.help());
48                         return 1;
49                 }
50
51                 int result = app_->main();
52                 Application *a = app_;
53                 app_ = 0;
54                 delete a;
55                 return result;
56         }
57         catch(const exception &e)
58         {
59                 bool handled = false;
60                 if(const Debug::ErrorReporter *er = Debug::ErrorReporter::get_current())
61                         handled = er->report_uncaught_exception(e);
62
63                 if(!handled)
64                 {
65                         IO::print(IO::cerr, "An uncaught exception occurred.\n");
66                         IO::print(IO::cerr, "  type:   %s\n", Debug::demangle(typeid(e).name()));
67                         IO::print(IO::cerr, "  what(): %s\n", e.what());
68                 }
69
70                 delete app_;
71
72                 return 124;
73         }
74 }
75
76 int Application::main()
77 {
78         done = false;
79         while(!done)
80                 tick();
81
82         return exit_code;
83 }
84
85 void Application::catch_signal(int s)
86 {
87         signal(s, &sighandler_);
88 }
89
90 void Application::exit(int c)
91 {
92         done = true;
93         exit_code = c;
94 }
95
96 void Application::sighandler_(int s)
97 {
98         app_->sighandler(s);
99 }
100
101
102 Application::Starter::Starter()
103 {
104         if(starter_)
105                 throw logic_error("Can't create more than one Starter instance");
106
107         starter_ = this;
108 }
109
110 } // namespace Msp