feisty meow concerns codebase  2.140
shutdown_alerter.cpp
Go to the documentation of this file.
1 
2 
3 
4 /*****************************************************************************\
5 * *
6 * Name : shutdown_alerter *
7 * Author : Chris Koeritz *
8 * *
9 *******************************************************************************
10 * Copyright (c) 2003-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
17 
18 #include "process_control.h"
19 #include "process_entry.h"
20 #include "shutdown_alerter.h"
21 
23 #include <basis/array.h>
24 #include <basis/astring.h>
25 #include <basis/mutex.h>
26 #include <filesystem/filename.h>
28 #include <structures/set.h>
30 #include <timely/time_control.h>
31 #include <timely/time_stamp.h>
32 #include <timely/timer_driver.h>
33 
34 #include <signal.h>
35 #include <stdio.h>
36 
37 using namespace application;
38 using namespace basis;
39 using namespace filesystem;
40 using namespace loggers;
41 using namespace processes;
42 using namespace structures;
43 using namespace timely;
44 
45 #define DEBUG_SHUTDOWN_ALERTER
46  // uncomment for noisy version.
47 
48 #undef LOG
49 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
50 
52 
53 SAFE_STATIC(astring, shutdown_alerter::_app_name, )
54 
55 bool &shutdown_alerter::_defunct() { static bool _defu = false; return _defu; }
56 
57 bool &shutdown_alerter::_saw_interrupt()
58 { static bool _saw = false; return _saw; }
59 
60 int &shutdown_alerter::_timer_period() { static int _tim = 0; return _tim; }
61 
63 
64 static shutdown_alerter *_global_shutdown_alerter = NULL_POINTER;
65  // this static object is set by the setup() method. it should only come
66  // into existence once during a program's lifetime.
67 
69 {
70 }
71 
73 {
74  set_defunct();
75  if (_global_shutdown_alerter) {
76  program_wide_timer().zap_timer(_global_shutdown_alerter);
77  }
78 }
79 
80 void shutdown_alerter::handle_startup() { /* nothing for base class. */ }
81 
82 void shutdown_alerter::handle_shutdown() { /* nothing for base class. */ }
83 
84 void shutdown_alerter::handle_timer() { /* nothing for base class. */ }
85 
86 void shutdown_alerter::handle_timer_callback()
87 {
88  // don't invoke the user's timer unless the object is still alive.
89  if (!is_defunct()) handle_timer();
90 }
91 
93 {
94  set_defunct();
95 }
96 
98 {
99  FUNCDEF("close_application");
100  process_entry_array procs;
101  process_control querier;
102 
103  // lookup process ids of apps.
104  bool got_list = querier.query_processes(procs);
105  if (!got_list) {
106  LOG("couldn't get process list.");
107  return false;
108  }
109  int_set pids;
110  got_list = querier.find_process_in_list(procs, app_name, pids);
111  if (!got_list) {
112  LOG("couldn't find process in the list of active ones.");
113  return true;
114  }
115 
116  // zap all of them using our signal.
117  for (int i = 0; i < pids.length(); i++) {
118 //would linux be better served with sigterm also?
119 #ifdef __UNIX__
120  kill(pids[i], SIGHUP);
121 #endif
122 #ifdef __WIN32__
123 //lame--goes to whole program.
124  raise(SIGTERM);
125 #endif
126 //hmmm: check results...
127  }
128 
129  return true;
130 }
131 
133 {
134  _saw_interrupt() = true; // save the status.
135  if (_global_shutdown_alerter) {
136  _global_shutdown_alerter->close_this_program();
137  }
138 }
139 
141 {
142  _defunct() = true;
143 }
144 
145 bool shutdown_alerter::setup(const astring &app_name, int timer_period)
146 {
147 //hmmm: make sure not already initted.
148 
149  // simple initializations first...
150  _timer_period() = timer_period;
151  _app_name() = app_name;
152 
153  _global_shutdown_alerter = this;
154 
155  // setup signal handler for HUP signal. this is the one used to tell us
156  // to leave.
157 #ifdef __UNIX__
158  signal(SIGHUP, handle_OS_signal);
159 #endif
160 
161  // setup a handler for interrupt (e.g. ctrl-C) also.
162  signal(SIGINT, handle_OS_signal);
163 #ifdef __WIN32__
164  signal(SIGBREAK, handle_OS_signal);
165 #endif
166 
167  return true;
168 }
169 
171  const astring &app_name, int timer_period)
172 {
173  FUNCDEF("launch_console");
174  if (!alert.setup(app_name, timer_period)) return false;
175 
176  alert.handle_startup(); // tell the program it has started up.
177 
178  // start a timer if they requested one.
179  if (_timer_period()) {
180  program_wide_timer().set_timer(_timer_period(), &alert);
181  }
182 
183 #ifdef DEBUG_SHUTDOWN_ALERTER
184  const int REPORT_CYCLE = 10 * SECOND_ms;
185  time_stamp next_report(REPORT_CYCLE);
186 #endif
187 
188  while (!alert.is_defunct()) {
189 #ifdef DEBUG_SHUTDOWN_ALERTER
190  if (time_stamp() >= next_report) {
191  LOG(a_sprintf("%s: shout out from my main thread yo.\n", _global_argv[0]));
192  next_report.reset(REPORT_CYCLE);
193  }
194 #endif
195  time_control::sleep_ms(42);
196  }
197  alert.handle_shutdown();
198  return true;
199 }
200 
201 /*
202 #ifdef __WIN32__
203 bool shutdown_alerter::launch_event_loop(shutdown_alerter &alert,
204  const astring &app_name, int timer_period)
205 {
206  if (!alert.setup(app_name, timer_period)) return false;
207  alert.handle_startup();
208 
209  if (timer_period)
210  program_wide_timer().set_timer(timer_period, this);
211 
212  MSG msg;
213  msg.hwnd = 0; msg.message = 0; msg.wParam = 0; msg.lParam = 0;
214  while (!alert.is_defunct() && (GetMessage(&msg, NULL_POINTER, 0, 0)) {
215  TranslateMessage(&msg);
216  DispatchMessage(&msg);
217  }
218  alert.handle_shutdown();
219 
220  return true;
221 }
222 #endif
223 */
224 
225 
226 
227 
228 
a_sprintf is a specialization of astring that provides printf style support.
Definition: astring.h:440
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
Provides a bridge to the operating system for information on processes.
static bool find_process_in_list(const process_entry_array &processes, const basis::astring &app_name, structures::int_set &pids)
uses a pre-existing list of "processes" to search for the "app_name".
bool query_processes(process_entry_array &to_fill)
finds the processes that are running and drops them into "to_fill".
a handy class that implements an array of process entries.
Definition: process_entry.h:60
A platform-independent way to alert a program that it should shut down immediately.
static bool is_defunct()
returns true if the object has been marked as defunct.
static void set_defunct()
used by the derived class to mark that this object is about to exit.
virtual void handle_timer()
called periodically if a timer period was specified.
bool setup(const basis::astring &app_name, int timer_period=0)
constructs a shutdown_alerter for the "app_name" specified.
static void handle_OS_signal(int sig_id)
processes the signal from the OS when its time to shut down.
static void close_this_program()
causes this particular application to begin shutting down.
shutdown_alerter()
constructor does very little; setup() is what begins operation.
static bool launch_console(shutdown_alerter &alert, const basis::astring &app_name, int timer_period=0)
this is used to begin execution of a console mode application.
virtual void handle_startup()
this function is called once the program has begun operation.
virtual void handle_shutdown()
called during the program's shutdown process.
virtual ~shutdown_alerter()
static bool close_application(const basis::astring &app_name)
attempts to close the application named "app_name".
A simple object that wraps a templated set of ints.
Definition: set.h:156
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
void reset()
sets the stamp time back to now.
Definition: time_stamp.cpp:59
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
Definition: definitions.h:48
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:54
Implements an application lock to ensure only one is running at once.
char ** _global_argv
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
const int SECOND_ms
Number of milliseconds in a second.
Definition: definitions.h:120
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
#define LOG(s)
#define SAFE_STATIC(type, func_name, parms)
Statically defines a singleton object whose scope is the program's lifetime.
#define program_wide_timer()
provides access to the singleton timer_driver.
Definition: timer_driver.h:108