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
37using namespace application;
38using namespace basis;
39using namespace filesystem;
40using namespace loggers;
41using namespace processes;
42using namespace structures;
43using 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
53SAFE_STATIC(astring, shutdown_alerter::_app_name, )
54
55bool &shutdown_alerter::_defunct() { static bool _defu = false; return _defu; }
56
57bool &shutdown_alerter::_saw_interrupt()
58{ static bool _saw = false; return _saw; }
59
60int &shutdown_alerter::_timer_period() { static int _tim = 0; return _tim; }
61
63
64static 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
71
73{
75 if (_global_shutdown_alerter) {
76 program_wide_timer().zap_timer(_global_shutdown_alerter);
77 }
78}
79
80void shutdown_alerter::handle_startup() { /* nothing for base class. */ }
81
82void shutdown_alerter::handle_shutdown() { /* nothing for base class. */ }
83
84void shutdown_alerter::handle_timer() { /* nothing for base class. */ }
85
86void 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
96
98{
99 FUNCDEF("close_application");
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
145bool 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
196 }
197 alert.handle_shutdown();
198 return true;
199}
200
201/*
202#ifdef __WIN32__
203bool 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
#define LOG(s)
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.
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.
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
static void sleep_ms(basis::un_int msec)
a system independent name for a forced snooze measured in milliseconds.
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.
#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.
A platform independent way to obtain the timestamp of a file.
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>
#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.