~ubuntu-branches/debian/sid/gsmartcontrol/sid

« back to all changes in this revision

Viewing changes to src/applib/cmdex.h

  • Committer: Package Import Robot
  • Author(s): Giuseppe Iuculano
  • Date: 2013-05-31 11:41:52 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130531114152-5ljhkuswwpt4kdwo
Tags: 0.8.7-1
* [314881d] Updated debian/watch
* [18ebada] Imported Upstream version 0.8.7
* [c2a1f1b] debian/rules: Provide build-arch and build-indep
* [d3036a4] Enabled Hardening Options
* [2edfb87] Refreshed patches and removed patches apllied upstream
* [ac3b953] Bump to standard versions 3.9.4
* [292c276] Remove quilt from depends

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**************************************************************************
2
2
 Copyright:
3
 
      (C) 2008 - 2011  Alexander Shaduri <ashaduri 'at' gmail.com>
 
3
      (C) 2008 - 2012  Alexander Shaduri <ashaduri 'at' gmail.com>
4
4
 License: See LICENSE_gsmartcontrol.txt
5
5
***************************************************************************/
6
6
 
16
16
 
17
17
 
18
18
 
19
 
/*
20
 
There are two ways to detect when the command exits:
21
 
 
22
 
1. Add a callback to signal_exited.
23
 
 
24
 
2. Manually poll stopped_cleanup_needed() (from the same thread).
25
 
 
26
 
In both cases, stopped_cleanup() must be called afterwards
27
 
(from the main thread).
28
 
*/
29
 
 
30
 
 
31
 
 
32
 
 
33
 
// inheriting from sigc::trackable automatically disconnects this class's
34
 
// slots upon destruction.
 
19
/// Command executor.
 
20
/// There are two ways to detect when the command exits:
 
21
/// 1. Add a callback to signal_exited.
 
22
/// 2. Manually poll stopped_cleanup_needed() (from the same thread).
 
23
/// In both cases, stopped_cleanup() must be called afterwards
 
24
/// (from the main thread).
35
25
class Cmdex : public hz::ErrorHolder<hz::SyncPolicyNone> {
36
 
 
37
26
        public:
38
27
 
39
 
                using hz::ErrorHolder<hz::SyncPolicyNone>::ptr_error_list_t;  // auto-deleting container
40
 
                using hz::ErrorHolder<hz::SyncPolicyNone>::error_list_t;
 
28
                using hz::ErrorHolder<hz::SyncPolicyNone>::ptr_error_list_t;  ///< Auto-deleting pointer container
 
29
                using hz::ErrorHolder<hz::SyncPolicyNone>::error_list_t;  ///< Error list type
41
30
 
 
31
                /// A function that translates the exit error code into a readable string
42
32
                typedef std::string (*exit_status_translator_func_t)(int, void*);
 
33
 
 
34
                /// A function that is called whenever a process exits.
43
35
                typedef void (*exited_callback_func_t)(void*);
44
36
 
45
37
 
46
 
                Cmdex(
47
 
                        // exit_status_translator_func_t translator_func,
48
 
                        exited_callback_func_t exited_cb = NULL, void* exited_cb_data = NULL
49
 
                        )
50
 
                        : running_(false), kill_signal_sent_(0), child_watch_handler_called_(false),
51
 
                        pid_(0), waitpid_status_(0),
52
 
                        timer_(g_timer_new()),
53
 
                        event_source_id_term(0), event_source_id_kill(0),
54
 
                        fd_stdout_(0), fd_stderr_(0), channel_stdout_(0), channel_stderr_(0),
55
 
                        channel_stdout_buffer_size_(100 * 1024), channel_stderr_buffer_size_(10 * 1024),  // 100K and 10K
56
 
                        event_source_id_stdout_(0), event_source_id_stderr_(0),
57
 
                        translator_func_(0), translator_func_data_(0),
58
 
                        exited_callback_(exited_cb), exited_callback_data_(exited_cb_data)
 
38
                /// Constructor
 
39
                Cmdex(exited_callback_func_t exited_cb = NULL, void* exited_cb_data = NULL)
 
40
                                : running_(false), kill_signal_sent_(0), child_watch_handler_called_(false),
 
41
                                pid_(0), waitpid_status_(0),
 
42
                                timer_(g_timer_new()),
 
43
                                event_source_id_term(0), event_source_id_kill(0),
 
44
                                fd_stdout_(0), fd_stderr_(0), channel_stdout_(0), channel_stderr_(0),
 
45
                                channel_stdout_buffer_size_(100 * 1024), channel_stderr_buffer_size_(10 * 1024),  // 100K and 10K
 
46
                                event_source_id_stdout_(0), event_source_id_stderr_(0),
 
47
                                translator_func_(0), translator_func_data_(0),
 
48
                                exited_callback_(exited_cb), exited_callback_data_(exited_cb_data)
59
49
                { }
60
50
 
61
51
 
62
52
 
63
 
                // Please don't destroy this object unless the child has exited. It will leak stuff
64
 
                // and possibly crash, etc... .
 
53
                /// Destructor. Don't destroy this object unless the child has exited. It will leak stuff
 
54
                /// and possibly crash, etc... .
65
55
                ~Cmdex()
66
56
                {
67
57
                        // This will help if object is destroyed after the command has exited, but before
75
65
                }
76
66
 
77
67
 
78
 
                // Call before execute.
79
 
                // Note: The command and the arguments _must_ be shell-escaped.
80
 
                // Use g_shell_quote() or Glib::shell_quote(). Note that each argument
81
 
                // must be escaped separately.
 
68
                /// Set the command to execute. Call before execute().
 
69
                /// Note: The command and the arguments _must_ be shell-escaped.
 
70
                /// Use g_shell_quote() or Glib::shell_quote(). Note that each argument
 
71
                /// must be escaped separately.
82
72
                void set_command(const std::string& command_exec, const std::string& command_args)
83
73
                {
84
74
                        command_exec_ = command_exec;
86
76
                }
87
77
 
88
78
 
89
 
                // launch the command.
 
79
                /// Launch the command.
90
80
                bool execute();
91
81
 
92
82
 
93
 
                // send SIGTERM(15) (terminate).
94
 
                // use after execute(). using it after the command has exited has no effect.
 
83
                /// Send SIGTERM(15) (terminate) to the child process.
 
84
                /// Use only after execute(). Using it after the command has exited has no effect.
95
85
                bool try_stop(hz::signal_t sig = hz::SIGNAL_SIGTERM);
96
86
 
97
87
 
98
 
                // Send SIGKILL(9) (kill). This signal cannot be overridden in child process.
99
 
                // use after execute(). using it after the command has exited has no effect.
100
 
                bool try_kill()
101
 
                {
102
 
                        return try_stop(hz::SIGNAL_SIGKILL);
103
 
                }
104
 
 
105
 
 
106
 
                // set a timeout (since call to this function) to terminate, kill or both (use 0 to ignore the parameter).
107
 
                // the timeouts will be unset automatically when the command exits.
108
 
                // This has an effect only if the command is running (after execute()).
 
88
                /// Send SIGKILL(9) (kill) to the child process. Same as
 
89
                /// try_stop(hz::SIGNAL_SIGKILL).
 
90
                /// Note that SIGKILL cannot be overridden in child process.
 
91
                bool try_kill();
 
92
 
 
93
 
 
94
                /// Set a timeout (since call to this function) to terminate the child process,
 
95
                /// kill it or both (use 0 to ignore the parameter).
 
96
                /// The timeouts will be unset automatically when the command exits.
 
97
                /// This has an effect only if the command is running (after execute()).
109
98
                void set_stop_timeouts(int term_timeout_msec = 0, int kill_timeout_msec = 0);
110
99
 
111
 
                // Unset timeouts. This will stop the timeout counters.
112
 
                // This has an effect only if the command is running (after execute()).
 
100
                /// Unset the terminate / kill timeouts. This will stop the timeout counters.
 
101
                /// This has an effect only if the command is running (after execute()).
113
102
                void unset_stop_timeouts();
114
103
 
115
104
 
116
 
                // If stopped_cleanup_needed() returned true, call this. The command
117
 
                // should be exited by this time. Must be called before the next execute().
 
105
                /// If stopped_cleanup_needed() returned true, call this. The command
 
106
                /// should be exited by this time. Must be called before the next execute().
118
107
                void stopped_cleanup();
119
108
 
120
109
 
121
 
                // Returns true if command has stopped.
122
 
                // Call repeatedly in a waiting function, after execute(). When returns true, call stopped_cleanup().
 
110
                /// Returns true if command has stopped.
 
111
                /// Call repeatedly in a waiting function, after execute().
 
112
                /// When it returns true, call stopped_cleanup().
123
113
                bool stopped_cleanup_needed()
124
114
                {
125
115
                        return (child_watch_handler_called_);
126
116
                }
127
117
 
128
118
 
129
 
                // The process is running. Note that if this returns false, it doesn't mean that
130
 
                // the io channels have been closed or that the data may be read safely. Poll
131
 
                // stopped_cleanup_needed() instead.
 
119
                /// Check if the process is running. Note that if this returns false, it doesn't mean that
 
120
                /// the io channels have been closed or that the data may be read safely. Poll
 
121
                /// stopped_cleanup_needed() instead.
132
122
                bool is_running() const
133
123
                {
134
124
                        return running_;
136
126
 
137
127
 
138
128
 
139
 
                // Call this before execution. There is a race-like condition - when the command
140
 
                // outputs something, the io channel reads it from fd to its buffer and the event
141
 
                // source callback is called. If the command dies, the io channel callback reads
142
 
                // the remaining data to the channel buffer.
143
 
                // Since the event source callbacks (which read from the buffer and empty it)
144
 
                // happen rather sporadically (from the glib loop), the buffer may not get read and
145
 
                // emptied at all (before the command exits). This is why it's necessary to have
146
 
                // a buffer size which potentially can hold _all_ the command output.
147
 
                // A way to fight this is to increase event source priority (which may not help).
148
 
                // Another way is to delay the command exit so that the event source callback
149
 
                // catches on and reads the buffer.
150
 
 
151
 
                // Use 0 to ignore the parameter. Call before execute().
 
129
                /// Call this before execution. There is a race-like condition - when the command
 
130
                /// outputs something, the io channel reads it from fd to its buffer and the event
 
131
                /// source callback is called. If the command dies, the io channel callback reads
 
132
                /// the remaining data to the channel buffer.
 
133
                /// Since the event source callbacks (which read from the buffer and empty it)
 
134
                /// happen rather sporadically (from the glib loop), the buffer may not get read and
 
135
                /// emptied at all (before the command exits). This is why it's necessary to have
 
136
                /// a buffer size which potentially can hold _all_ the command output.
 
137
                /// A way to fight this is to increase event source priority (which may not help).
 
138
                /// Another way is to delay the command exit so that the event source callback
 
139
                /// catches on and reads the buffer.
 
140
                // Use 0 to ignore the parameter. Call this before execute().
152
141
                void set_buffer_sizes(int stdout_buffer_size = 0, int stderr_buffer_size = 0)
153
142
                {
154
143
                        if (stdout_buffer_size)
159
148
 
160
149
 
161
150
 
162
 
                // If stdout_make_str_as_available_ is false, call this after stopped_cleanup(),
163
 
                // before next execute(). If it's true, you may call this before the command has
164
 
                // stopped, but it will decrease performance significantly.
 
151
                /// If stdout_make_str_as_available_ is false, call this after stopped_cleanup(),
 
152
                /// before next execute(). If it's true, you may call this before the command has
 
153
                /// stopped, but it will decrease performance significantly.
165
154
                std::string get_stdout_str(bool clear_existing = false)
166
155
                {
167
156
                        // debug_out_dump("app", str_stdout_);
174
163
                }
175
164
 
176
165
 
177
 
                // See notes on get_stdout_str().
 
166
                /// See notes on get_stdout_str().
178
167
                std::string get_stderr_str(bool clear_existing = false)
179
168
                {
180
169
                        if (clear_existing) {
186
175
                }
187
176
 
188
177
 
189
 
                // Return execution time, in seconds. Call after execute().
 
178
                /// Return execution time, in seconds. Call this after execute().
190
179
                double get_execution_time()
191
180
                {
192
181
                        gulong microsec = 0;
194
183
                }
195
184
 
196
185
 
197
 
                // this will disconnect earlier slots. Call before execute().
 
186
                /// Set exit status translator callback, disconnecting the old one.
 
187
                /// Call only before execute().
198
188
                void set_exit_status_translator(exit_status_translator_func_t func, void* user_data)
199
189
                {
200
190
                        translator_func_ = func;
202
192
                }
203
193
 
204
194
 
205
 
                // You can use stopped_cleanup_needed() polling instead.
 
195
                /// Set exit notifier callback, disconnecting the old one.
 
196
                /// You can poll stopped_cleanup_needed() instead of using this function.
206
197
                void set_exited_callback(exited_callback_func_t func, void* user_data)
207
198
                {
208
199
                        exited_callback_ = func;
213
204
 
214
205
        // these are sorta-private
215
206
 
216
 
                // for passing to callback
 
207
                /// Channel type, for passing to callbacks
217
208
                enum channel_t {
218
209
                        channel_type_stdout,
219
210
                        channel_type_stderr
222
213
 
223
214
                // Callbacks (Note: These are called by the real callbacks)
224
215
 
 
216
                /// Child watch handler
225
217
                static void on_child_watch_handler(GPid arg_pid, int waitpid_status, gpointer data);
226
218
 
 
219
                /// Channel I/O handler
227
220
                static gboolean on_channel_io(GIOChannel* source,
228
221
                                GIOCondition cond, Cmdex* self, channel_t type);
229
222
 
231
224
        private:
232
225
 
233
226
 
 
227
                /// Clean up the member variables and shut down the channels if needed.
234
228
                void cleanup_members()
235
229
                {
236
230
                        kill_signal_sent_ = 0;
257
251
 
258
252
 
259
253
                // default command and its args. std::strings, not ustrings.
260
 
                std::string command_exec_;  // binary name. NOT affected by cleanup().
261
 
                std::string command_args_;  // args that always go with binary. NOT affected by cleanup().
262
 
 
263
 
 
264
 
                bool running_;  // child process is running now. NOT affected by cleanup().
265
 
                int kill_signal_sent_;  // command has been sent this signal to terminate
266
 
                bool child_watch_handler_called_;  // true after child_watch_handler callback, before stopped_cleanup().
267
 
 
268
 
                GPid pid_;  // int in Unix, pointer in win32
269
 
                int waitpid_status_;  // after the command is stopped, before cleanup, this will be available.
270
 
 
271
 
 
272
 
                GTimer* timer_;  // keep track of elapsed time since command execution. not used by this class, but may be handy.
273
 
 
274
 
                int event_source_id_term;
275
 
                int event_source_id_kill;
276
 
 
277
 
 
278
 
                int fd_stdout_;
279
 
                int fd_stderr_;
280
 
 
281
 
                GIOChannel* channel_stdout_;
282
 
                GIOChannel* channel_stderr_;
283
 
 
284
 
                int channel_stdout_buffer_size_;  // NOT affected by cleanup().
285
 
                int channel_stderr_buffer_size_;  // NOT affected by cleanup().
286
 
 
287
 
                int event_source_id_stdout_;
288
 
                int event_source_id_stderr_;
289
 
 
290
 
                std::string str_stdout_;  // NOT affected by cleanup().
291
 
                std::string str_stderr_;  // NOT affected by cleanup().
 
254
                std::string command_exec_;  /// Binary name to execute. NOT affected by cleanup_members().
 
255
                std::string command_args_;  /// Arguments that always go with the binary. NOT affected by cleanup_members().
 
256
 
 
257
 
 
258
                bool running_;  ///< If true, the child process is running now. NOT affected by cleanup_members().
 
259
                int kill_signal_sent_;  ///< If non-zero, the process has been sent this signal to terminate
 
260
                bool child_watch_handler_called_;  ///< true after child_watch_handler callback, before stopped_cleanup().
 
261
 
 
262
                GPid pid_;  ///< Process ID. int in Unix, pointer in win32
 
263
                int waitpid_status_;  ///< After the command is stopped, before cleanup, this will be available (waitpid() status).
 
264
 
 
265
 
 
266
                GTimer* timer_;  ///< Keeps track of elapsed time since command execution. Value is not used by this class, but may be handy.
 
267
 
 
268
                int event_source_id_term;  ///< Timeout event source ID for SIGTERM.
 
269
                int event_source_id_kill;  ///< Timeout event source ID for SIGKILL.
 
270
 
 
271
 
 
272
                int fd_stdout_;  ///< stdout file descriptor
 
273
                int fd_stderr_;  ///< stderr file descriptor
 
274
 
 
275
                GIOChannel* channel_stdout_;  ///< stdout channel
 
276
                GIOChannel* channel_stderr_;  ///< stderr channel
 
277
 
 
278
                int channel_stdout_buffer_size_;  ///< stdout channel buffer size. NOT affected by cleanup_members().
 
279
                int channel_stderr_buffer_size_;  ///< stderr channel buffer size. NOT affected by cleanup_members().
 
280
 
 
281
                int event_source_id_stdout_;  ///< IO watcher event source ID for stdout
 
282
                int event_source_id_stderr_;  ///< IO watcher event source ID for stderr
 
283
 
 
284
                std::string str_stdout_;  ///< stdout data read during execution. NOT affected by cleanup_members().
 
285
                std::string str_stderr_;  ///< stderr data read during execution. NOT affected by cleanup_members().
292
286
 
293
287
 
294
288
                // signals
295
289
 
296
290
                // convert command exit status to message string
297
 
                exit_status_translator_func_t translator_func_;  // NOT affected by cleanup().
298
 
                void* translator_func_data_;
 
291
                exit_status_translator_func_t translator_func_;  ///< Exit status translator function. NOT affected by cleanup_members().
 
292
                void* translator_func_data_;  ///< Data to supply to the exit status translator function.
299
293
 
300
294
                // "command exited" signal callback.
301
 
                exited_callback_func_t exited_callback_;  // NOT affected by cleanup().
302
 
                void* exited_callback_data_;
 
295
                exited_callback_func_t exited_callback_;  ///< Exit notifier function. NOT affected by cleanup_members().
 
296
                void* exited_callback_data_;  ///< Data to supply to the exit notifier function.
303
297
 
304
298
 
305
299
};