00001 #ifndef SHUTDOWN_ALERTER_IMPLEMENTATION_FILE
00002 #define SHUTDOWN_ALERTER_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "process_control.h"
00019 #include "process_entry.h"
00020 #include "shutdown_alerter.h"
00021
00022 #include <basis/array.cpp>
00023 #include <basis/istring.h>
00024 #include <basis/log_base.h>
00025 #include <basis/mutex.h>
00026 #include <basis/portable.h>
00027 #include <basis/set.cpp>
00028 #include <data_struct/static_memory_gremlin.h>
00029 #include <mechanisms/time_stamp.h>
00030 #include <opsystem/filename.h>
00031 #include <opsystem/timer_driver.h>
00032
00033 #include <signal.h>
00034
00035
00036
00037
00038 #undef LOG
00039 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00040
00042
00043 SAFE_STATIC(istring_object, shutdown_alerter::_app_name, )
00044
00045 bool &shutdown_alerter::_defunct() { static bool _defu = false; return _defu; }
00046
00047 bool &shutdown_alerter::_saw_interrupt()
00048 { static bool _saw = false; return _saw; }
00049
00050 int &shutdown_alerter::_timer_period() { static int _tim = 0; return _tim; }
00051
00053
00054 static shutdown_alerter *_global_shutdown_alerter = NIL;
00055
00056
00057
00058 shutdown_alerter::shutdown_alerter()
00059 {
00060 }
00061
00062 shutdown_alerter::~shutdown_alerter()
00063 {
00064 set_defunct();
00065 if (_global_shutdown_alerter) {
00066 program_wide_timer().zap_timer(_global_shutdown_alerter);
00067 }
00068 }
00069
00070 void shutdown_alerter::handle_startup() { }
00071
00072 void shutdown_alerter::handle_shutdown() { }
00073
00074 void shutdown_alerter::handle_timer() { }
00075
00076 void shutdown_alerter::handle_timer_callback()
00077 {
00078
00079 if (!is_defunct()) handle_timer();
00080 }
00081
00082 void shutdown_alerter::close_this_program()
00083 {
00084 set_defunct();
00085 }
00086
00087 bool shutdown_alerter::close_application(const istring &app_name)
00088 {
00089 FUNCDEF("close_application");
00090 process_entry_array procs;
00091 process_control querier;
00092
00093
00094 bool got_list = querier.query_processes(procs);
00095 if (!got_list) {
00096 LOG("couldn't get process list.");
00097 return false;
00098 }
00099 int_set pids;
00100 got_list = querier.find_process_in_list(procs, app_name, pids);
00101 if (!got_list) {
00102 LOG("couldn't find process in the list of active ones.");
00103 return true;
00104 }
00105
00106
00107 for (int i = 0; i < pids.length(); i++) {
00108
00109 #ifdef __UNIX__
00110 kill(pids[i], SIGHUP);
00111 #endif
00112 #ifdef __WIN32__
00113
00114 raise(SIGTERM);
00115 #endif
00116
00117 }
00118
00119 return true;
00120 }
00121
00122 void shutdown_alerter::handle_OS_signal(int formal(sig_id))
00123 {
00124 _saw_interrupt() = true;
00125 if (_global_shutdown_alerter) {
00126 _global_shutdown_alerter->close_this_program();
00127 }
00128 }
00129
00130 void shutdown_alerter::set_defunct()
00131 {
00132 _defunct() = true;
00133 }
00134
00135 bool shutdown_alerter::setup(const istring &app_name, int timer_period)
00136 {
00137
00138
00139
00140 _timer_period() = timer_period;
00141 _app_name() = app_name;
00142
00143 _global_shutdown_alerter = this;
00144
00145
00146
00147 #ifdef __UNIX__
00148 signal(SIGHUP, handle_OS_signal);
00149 #endif
00150
00151
00152 signal(SIGINT, handle_OS_signal);
00153 #ifdef __WIN32__
00154 signal(SIGBREAK, handle_OS_signal);
00155 #endif
00156
00157 return true;
00158 }
00159
00160 bool shutdown_alerter::launch_console(shutdown_alerter &alert,
00161 const istring &app_name, int timer_period)
00162 {
00163 FUNCDEF("launch_console");
00164 if (!alert.setup(app_name, timer_period)) return false;
00165
00166 alert.handle_startup();
00167
00168
00169 if (_timer_period()) {
00170 program_wide_timer().set_timer(_timer_period(), &alert);
00171 }
00172
00173 #ifdef DEBUG_SHUTDOWN_ALERTER
00174 time_stamp next_report(10 * SECOND_ms);
00175 #endif
00176
00177 while (!alert.is_defunct()) {
00178 #ifdef DEBUG_SHUTDOWN_ALERTER
00179 if (time_stamp() >= next_report) {
00180 printf("%s: shout out from my main thread yo.\n", __argv[0]);
00181 next_report.reset(10 * SECOND_ms);
00182 }
00183 #endif
00184 portable::sleep_ms(42);
00185 }
00186 alert.handle_shutdown();
00187 return true;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 #endif //SHUTDOWN_ALERTER_IMPLEMENTATION_FILE
00217