feisty meow concerns codebase  2.140
hoople_service.cpp
Go to the documentation of this file.
1 // Name : hoople_service
3 // Author : Chris Koeritz
5 // Copyright (c) 2000-$now By Author. This program is free software; you can
6 // redistribute it and/or modify it under the terms of the GNU General Public
7 // License as published by the Free Software Foundation:
8 // http://www.gnu.org/licenses/gpl.html
9 // or under the terms of the GNU Library license:
10 // http://www.gnu.org/licenses/lgpl.html
11 // at your preference. Those licenses describe your legal rights to this
12 // software, and no other rights or warranties apply.
13 // Please send updates for this code to: fred@gruntose.com -- Thanks, fred.
15 
16 #include "hoople_service.h"
17 
18 #include <basis/array.h>
19 #include <basis/mutex.h>
20 #include <filesystem/filename.h>
25 #include <structures/set.h>
27 #include <timely/time_control.h>
28 #include <timely/time_stamp.h>
29 #include <timely/timer_driver.h>
30 
31 #include <signal.h>
32 
33 using namespace basis;
34 using namespace filesystem;
35 using namespace loggers;
36 using namespace processes;
37 using namespace structures;
38 using namespace timely;
39 
40 //#define DEBUG_HOOPLE_SERVICE
41  // uncomment for noisy version.
42 
43 #undef LOG
44 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
45 
46 namespace application {
47 
49 
50 SAFE_STATIC(astring, hoople_service::_app_name, )
51 
52 bool &hoople_service::_defunct() { static bool _defu = false; return _defu; }
53 
54 bool &hoople_service::_saw_interrupt()
55 { static bool _saw = false; return _saw; }
56 
57 int &hoople_service::_timer_period() { static int _tim = 0; return _tim; }
58 
60 
61 static hoople_service *_global_hoople_service = NULL_POINTER;
62  // this static object is set by the setup() method. it should only come
63  // into existence once during a program's lifetime.
64 
65 hoople_service::hoople_service()
66 {
67 }
68 
69 hoople_service::~hoople_service()
70 {
71  make_defunct();
72  if (_global_hoople_service) {
73  program_wide_timer().zap_timer(_global_hoople_service);
74  }
75 }
76 
77 void hoople_service::handle_startup() { /* nothing for base class. */ }
78 
79 void hoople_service::handle_shutdown() { /* nothing for base class. */ }
80 
81 void hoople_service::handle_timer() { /* nothing for base class. */ }
82 
83 void hoople_service::handle_timer_callback()
84 {
85  // don't invoke the user's timer unless the object is still alive.
86  if (!is_defunct()) handle_timer();
87 }
88 
89 void hoople_service::close_this_program()
90 {
91  make_defunct();
92 }
93 
94 bool hoople_service::close_application(const astring &app_name)
95 {
96  FUNCDEF("close_application");
97  process_entry_array procs;
98  process_control querier;
99 
100  // lookup process ids of apps.
101  bool got_list = querier.query_processes(procs);
102  if (!got_list) {
103  LOG(astring("couldn't get process list."));
104  return false;
105  }
106  int_set pids;
107  got_list = querier.find_process_in_list(procs, app_name, pids);
108  if (!got_list) {
109  LOG(astring("couldn't find process in the list of active ones."));
110  return true;
111  }
112 
113  // zap all of them using our signal.
114  for (int i = 0; i < pids.length(); i++) {
115 //hmmm: would linux be better served with sigterm instead, like we used to do for windoze?
116 //#ifndef _MSC_VER
117  kill(pids[i], SIGHUP);
118 //#else
120 // raise(SIGTERM);
121 //#endif
122 //hmmm: check results...
123  }
124 
125  return true;
126 }
127 
128 void hoople_service::handle_OS_signal(int formal(sig_id))
129 {
130  _saw_interrupt() = true; // save the status.
131  if (_global_hoople_service) {
132  _global_hoople_service->close_this_program();
133  }
134 }
135 
136 void hoople_service::make_defunct()
137 {
138  _defunct() = true;
139 }
140 
141 bool hoople_service::setup(const astring &app_name, int timer_period)
142 {
143 //hmmm: make sure not already initted.
144 
145  // simple initializations first...
146  _timer_period() = timer_period;
147  _app_name() = app_name;
148 
149  _global_hoople_service = this;
150 
151  // setup signal handler for HUP signal. this is the one used to tell us
152  // to leave.
153 //#ifndef _MSC_VER
154  signal(SIGHUP, handle_OS_signal);
155 //#endif
156 
157  // setup a handler for interrupt (e.g. ctrl-C) also.
158  signal(SIGINT, handle_OS_signal);
159 //#ifdef _MSC_VER
160 // signal(SIGBREAK, handle_OS_signal);
161 //#endif
162 
163  return true;
164 }
165 
166 bool hoople_service::launch_console(hoople_service &alert,
167  const astring &app_name, int timer_period)
168 {
169 #ifdef DEBUG_HOOPLE_SERVICE
170  FUNCDEF("launch_console");
171 #endif
172  if (!alert.setup(app_name, timer_period)) return false;
173 
174  alert.handle_startup(); // tell the program it has started up.
175 
176  // start a timer if they requested one.
177  if (_timer_period()) {
178  program_wide_timer().set_timer(_timer_period(), &alert);
179  }
180 
181 #ifdef DEBUG_HOOPLE_SERVICE
182  time_stamp next_report(10 * SECOND_ms);
183 #endif
184 
185  while (!alert.is_defunct()) {
186 #ifdef DEBUG_HOOPLE_SERVICE
187  if (time_stamp() >= next_report) {
188  printf("%s: shout out from my main thread yo.\n", _global_argv[0]);
189  next_report.reset(10 * SECOND_ms);
190  }
191 #endif
192  time_control::sleep_ms(42);
193  }
194  alert.handle_shutdown();
195  return true;
196 }
197 
198 /*
199 #ifdef __WIN32__
200 bool hoople_service::launch_event_loop(hoople_service &alert,
201  const astring &app_name, int timer_period)
202 {
203  if (!alert.setup(app_name, timer_period)) return false;
204  alert.handle_startup();
205 
206  if (timer_period)
207  program_wide_timer().set_timer(timer_period, this);
208 
209  MSG msg;
210  msg.hwnd = 0; msg.message = 0; msg.wParam = 0; msg.lParam = 0;
211  while (!alert.is_defunct() && (GetMessage(&msg, NULL_POINTER, 0, 0)) {
212  TranslateMessage(&msg);
213  DispatchMessage(&msg);
214  }
215  alert.handle_shutdown();
216 
217  return true;
218 }
219 #endif
220 */
221 
222 } //namespace.
223 
A platform-independent way to alert a program that it should shut down immediately.
virtual void handle_startup()
this function is called once the program has begun operation.
static bool is_defunct()
returns true if the object has been marked as defunct.
bool setup(const basis::astring &app_name, int timer_period=0)
constructs a hoople_service for the "app_name" specified.
static void close_this_program()
causes this particular application to begin shutting down.
virtual void handle_shutdown()
called during the program's shutdown process.
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 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:57
#define LOG(s)
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 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