first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / application / launch_manager.h
1
2 // current bad issues:
3 //
4 // this class does not really provide a notion of the process name AND process id as being
5 // a pair one can operate on.  mostly it assumes a bunch of singletons or that it's okay
6 // to whack all of them.
7 // that could be fixed by making the procname+procid pair into a unit in all functions,
8 // and make kill_all be a specialization of that.
9
10
11 #ifndef LAUNCH_MANAGER_CLASS
12 #define LAUNCH_MANAGER_CLASS
13
14 /*****************************************************************************\
15 *                                                                             *
16 *  Name   : launch_manager
17 *  Author : Chris Koeritz
18 *                                                                             *
19 *******************************************************************************
20 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
21 * redistribute it and/or modify it under the terms of the GNU General Public  *
22 * License as published by the Free Software Foundation; either version 2 of   *
23 * the License or (at your option) any later version.  This is online at:      *
24 *     http://www.fsf.org/copyleft/gpl.html                                    *
25 * Please send any updates to: fred@gruntose.com                               *
26 \*****************************************************************************/
27
28 #include <basis/astring.h>
29 #include <basis/mutex.h>
30 #include <basis/outcome.h>
31 #include <basis/contracts.h>
32 #include <processes/configured_applications.h>
33 #include <processes/process_entry.h>
34 #include <processes/process_control.h>
35 #include <structures/set.h>
36 #include <timely/time_stamp.h>
37
38 namespace application {
39
40 class graceful_array;
41 class launch_manager_thread;
42
43 //! Provides methods for starting, stopping and checking on processes.
44 /*!
45   This includes support for graceful shutdowns and background handling of
46   exiting processes.
47 */
48
49 class launch_manager : public virtual basis::root_object
50 {
51 public:
52   launch_manager(processes::configured_applications &config);
53     //!< the launch_manager needs a configuration set to work with.
54
55   virtual ~launch_manager();
56
57   DEFINE_CLASS_NAME("launch_manager");
58
59   enum outcomes {
60     OKAY = basis::common::OKAY,
61     EXISTING = basis::common::EXISTING,
62       //!< the entry already exists and overwriting is disallowed.
63     ACCESS_DENIED = basis::common::ACCESS_DENIED,
64       //!< the requested operation was not permitted.
65
66     DEFINE_API_OUTCOME(FILE_NOT_FOUND, -53, "The file specified for the "
67         "application doesn't exist, as far as we can tell"),
68     DEFINE_API_OUTCOME(NO_PRODUCT, -54, "The product specified does not exist"),
69     DEFINE_API_OUTCOME(NO_APPLICATION, -55, "The application is not listed for "
70         "the product"),
71     DEFINE_API_OUTCOME(NOT_RUNNING, -56, "The program is not currently active, "
72         "according to the OS process list"),
73     DEFINE_API_OUTCOME(BAD_PROGRAM, -57, "The file existed but doesn't appear "
74         "to be a valid program image"),
75     DEFINE_API_OUTCOME(NO_ANCHOR, -58, "This occurs when the graceful shutdown "
76         "process cannot find the special anchor window that implements the "
77         "client side of a graceful shutdown"),
78     DEFINE_API_OUTCOME(LAUNCH_FAILED, -59, "The program existed and seemed "
79         "valid but its launch failed for some reason"),
80     DEFINE_API_OUTCOME(FROZEN, -60, "The application is broken somehow; the "
81         "system reports it as non-responsive"),
82     // note that these values are reversed, since the ordering is negative.
83     FIRST_OUTCOME = FROZEN,  // hold onto start of range.
84     LAST_OUTCOME = FILE_NOT_FOUND // hold onto end of range.
85   };
86
87   static const char *outcome_name(const basis::outcome &to_name);
88     //!< returns the text associated with "to_name".
89
90   basis::outcome launch_now(const basis::astring &product, const basis::astring &app_name,
91           const basis::astring &parameters);
92     //!< starts the application "app_name" now.
93     /*!< causes the program with "app_name" that's listed for the "product" to
94     be started with the "parameters".  this can fail if the application
95     isn't listed or if the program can't be found or if the process can't
96     be created. */
97
98   basis::outcome launch_at_startup(const basis::astring &product, const basis::astring &app_name,
99           const basis::astring &parameters, int one_shot);
100     //!< records an entry for the "app_name" to be launched at startup.
101     /*!< this does not launch the application now.  if "one_shot" is true, the
102     application will only be started once and then removed from the list. */
103
104   basis::outcome remove_from_startup(const basis::astring &product, const basis::astring &app_name);
105     //!< takes the "app_name" out of the startup list.
106
107   basis::outcome query_application(const basis::astring &product, const basis::astring &app_name);
108     //!< retrieves the current state of the program with "app_name".
109
110   basis::outcome zap_process(const basis::astring &product, const basis::astring &app_name,
111           bool graceful);
112     //!< zaps the process named "app_name".
113     /*!< if "graceful" is true, then the clean shutdown process is attempted.
114     otherwise the application is harshly terminated. */
115
116   void add_gag_exclusion(const basis::astring &exclusion);
117     //!< add an application that isn't subject to gagging.
118     /*!< if the launch_manager is gagged, the excluded applications can
119     still be started. */
120   void add_tracking_exclusion(const basis::astring &exclusion);
121     //!< apps that aren't tracked when running.
122     /*!< if a zap is attempted on one of these applications, then
123     the process is not shut down. */
124
125   basis::outcome shut_down_launching_services(const basis::astring &secret_word);
126     //!< closes down the ability of clients to launch applications.
127     /*!< the checking and shut down functions continue to operate.  this is
128     intended for use prior to a restart of the application controller, in
129     order to ensure that no remote clients can start new servers on this
130     machine. */
131
132   basis::outcome reenable_launching_services(const basis::astring &secret_word);
133     //!< undoes the gagging that the above "shut_down" function does.
134     /*!< this allows the launch_manager to continue operating normally. */
135
136   bool services_disabled() const { return _stop_launching; }
137     //!< returns true if the capability to launch new processes is revoked.
138
139   void push_timed_activities(processes::process_entry_array &processes);
140     //!< keeps any periodic activities going.
141     /*!< this includes such tasks as zapping processes that have gone beyond
142     their time limit for graceful shutdown. */
143
144   void stop_everything();
145     //!< closes down the operation of this object.
146
147 private:
148   processes::configured_applications &_configs;  //!< manages the entries for companies.
149   bool _started_initial_apps;  //!< true if we launched the boot apps.
150   launch_manager_thread *_checker;  //!< keeps periodic activities going.
151   basis::mutex *_config_lock;  //!< the synchronizer for our configuration entries.
152   graceful_array *_going_down;  //!< record of graceful shutdowns in progress.
153   basis::mutex *_zombie_lock;  //!< the synchronizer for the dying processes.
154   graceful_array *_our_kids;  //!< the processes we've started.
155   basis::mutex *_scamp_lock;  //!< the synchronizer for the list of children.
156   bool _stop_launching;  //!< true if no launches should be allowed any more.
157   timely::time_stamp *_startup_time;
158     //!< the time we feel it's safe to launch the startup apps.
159     /*!< we delay this some so that the launch_manager doesn't immediately
160     soak up too much CPU. */
161   processes::process_control *_procs;  //!< gives us access to the process list.
162   structures::string_set *_gag_exclusions;  //!< apps that aren't subject to gag law.
163   structures::string_set *_tracking_exclusions;  //!< apps that aren't tracked when running.
164
165   bool get_processes(processes::process_entry_array &processes);
166     //!< grabs the list of "processes" or returns false.
167
168   bool find_process(const basis::astring &app_name, structures::int_set &pids);
169     //!< locates any instances of "app_name" and returns process ids in "pids".
170
171   basis::outcome start_graceful_close(const basis::astring &product, const basis::astring &app_name);
172     //!< attempts to close the "app_name".
173     /*!< if the application doesn't shut down within the time limit, it is
174     eventually zapped harshly. */
175
176   void launch_startup_apps();
177     //!< iterates over the list of startup apps and creates a process for each.
178
179   void stop_all_kids();
180     //!< closes all dependent processes when its time to stop the service.
181 };
182
183 } //namespace.
184
185 #endif
186