1    	/*
2    	 * Copyright 2004-2026 the Pacemaker project contributors
3    	 *
4    	 * The version control history for this file may have further details.
5    	 *
6    	 * This source code is licensed under the GNU Lesser General Public License
7    	 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8    	 */
9    	
10   	#include <crm_internal.h>
11   	
12   	#include <stdbool.h>
13   	#include <stdlib.h>
14   	#include <string.h>
15   	#include <signal.h>
16   	#include <errno.h>
17   	
18   	#include <sys/wait.h>
19   	
20   	#include <crm/crm.h>
21   	#include <crm/common/xml.h>
22   	#include <crm/common/mainloop.h>
23   	
24   	#include <qb/qbarray.h>
25   	
26   	struct trigger_s {
27   	    GSource source;
28   	    gboolean running;
29   	    gboolean trigger;
30   	    void *user_data;
31   	    unsigned int id;
32   	};
33   	
34   	struct mainloop_timer_s {
35   	        unsigned int id;
36   	        unsigned int period_ms;
37   	        bool repeat;
38   	        char *name;
39   	        GSourceFunc cb;
40   	        void *userdata;
41   	};
42   	
43   	static GHashTable *mainloop_children = NULL;
44   	static qb_array_t *gio_map = NULL;
45   	
46   	static void
47   	child_free(mainloop_child_t *child)
48   	{
49   	    if (child->timerid != 0) {
50   	        pcmk__trace("Removing timer %d", child->timerid);
51   	        g_source_remove(child->timerid);
52   	        child->timerid = 0;
53   	    }
54   	
55   	    free(child->desc);
56   	    free(child);
57   	}
58   	
59   	static gboolean
60   	crm_trigger_prepare(GSource *source, int *timeout)
61   	{
62   	    crm_trigger_t *trig = (crm_trigger_t *) source;
63   	
64   	    /* cluster-glue's FD and IPC related sources make use of
65   	     * g_source_add_poll() but do not set a timeout in their prepare
66   	     * functions
67   	     *
68   	     * This means mainloop's poll() will block until an event for one
69   	     * of these sources occurs - any /other/ type of source, such as
70   	     * this one or g_idle_*, that doesn't use g_source_add_poll() is
71   	     * S-O-L and won't be processed until there is something fd-based
72   	     * happens.
73   	     *
74   	     * Luckily the timeout we can set here affects all sources and
75   	     * puts an upper limit on how long poll() can take.
76   	     *
77   	     * So unconditionally set a small-ish timeout, not too small that
78   	     * we're in constant motion, which will act as an upper bound on
79   	     * how long the signal handling might be delayed for.
80   	     */
81   	    *timeout = 500;             /* Timeout in ms */
82   	
83   	    return trig->trigger;
84   	}
85   	
86   	static gboolean
87   	crm_trigger_check(GSource * source)
88   	{
89   	    crm_trigger_t *trig = (crm_trigger_t *) source;
90   	
91   	    return trig->trigger;
92   	}
93   	
94   	/*!
95   	 * \internal
96   	 * \brief GSource dispatch function for crm_trigger_t
97   	 *
98   	 * \param[in] source        crm_trigger_t being dispatched
99   	 * \param[in] callback      Callback passed at source creation
100  	 * \param[in,out] userdata  User data passed at source creation
101  	 *
102  	 * \return G_SOURCE_REMOVE to remove source, G_SOURCE_CONTINUE to keep it
103  	 */
104  	static gboolean
105  	crm_trigger_dispatch(GSource *source, GSourceFunc callback, void *userdata)
106  	{
107  	    gboolean rc = G_SOURCE_CONTINUE;
108  	    crm_trigger_t *trig = (crm_trigger_t *) source;
109  	
110  	    if (trig->running) {
111  	        /* Wait until the existing job is complete before starting the next one */
112  	        return G_SOURCE_CONTINUE;
113  	    }
114  	    trig->trigger = FALSE;
115  	
116  	    if (callback) {
117  	        int callback_rc = callback(trig->user_data);
118  	
119  	        if (callback_rc < 0) {
120  	            pcmk__trace("Trigger handler %p not yet complete", trig);
121  	            trig->running = TRUE;
122  	        } else if (callback_rc == 0) {
123  	            rc = G_SOURCE_REMOVE;
124  	        }
125  	    }
126  	    return rc;
127  	}
128  	
129  	static void
130  	crm_trigger_finalize(GSource * source)
131  	{
132  	    pcmk__trace("Trigger %p destroyed", source);
133  	}
134  	
135  	static GSourceFuncs crm_trigger_funcs = {
136  	    crm_trigger_prepare,
137  	    crm_trigger_check,
138  	    crm_trigger_dispatch,
139  	    crm_trigger_finalize,
140  	};
141  	
142  	static crm_trigger_t *
143  	mainloop_setup_trigger(GSource * source, int priority,
144  	                       int (*dispatch)(void *user_data), void *userdata)
145  	{
146  	    crm_trigger_t *trigger = NULL;
147  	
148  	    trigger = (crm_trigger_t *) source;
149  	
150  	    trigger->id = 0;
151  	    trigger->trigger = FALSE;
152  	    trigger->user_data = userdata;
153  	
154  	    if (dispatch) {
155  	        g_source_set_callback(source, dispatch, trigger, NULL);
156  	    }
157  	
158  	    g_source_set_priority(source, priority);
159  	    g_source_set_can_recurse(source, FALSE);
160  	
161  	    trigger->id = g_source_attach(source, NULL);
162  	    return trigger;
163  	}
164  	
165  	void
166  	mainloop_trigger_complete(crm_trigger_t * trig)
167  	{
168  	    pcmk__trace("Trigger handler %p complete", trig);
169  	    trig->running = FALSE;
170  	}
171  	
172  	/*!
173  	 * \brief Create a trigger to be used as a mainloop source
174  	 *
175  	 * \param[in] priority  Relative priority of source (lower number is higher priority)
176  	 * \param[in] dispatch  Trigger dispatch function (should return 0 to remove the
177  	 *                      trigger from the mainloop, -1 if the trigger should be
178  	 *                      kept but the job is still running and not complete, and
179  	 *                      1 if the trigger should be kept and the job is complete)
180  	 * \param[in] userdata  Pointer to pass to \p dispatch
181  	 *
182  	 * \return Newly allocated mainloop source for trigger
183  	 */
184  	crm_trigger_t *
185  	mainloop_add_trigger(int priority, int (*dispatch) (void *user_data),
186  	                     void *userdata)
187  	{
188  	    GSource *source = NULL;
189  	
190  	    pcmk__assert(sizeof(crm_trigger_t) > sizeof(GSource));
191  	    source = g_source_new(&crm_trigger_funcs, sizeof(crm_trigger_t));
192  	
193  	    return mainloop_setup_trigger(source, priority, dispatch, userdata);
194  	}
195  	
196  	void
197  	mainloop_set_trigger(crm_trigger_t * source)
198  	{
199  	    if(source) {
200  	        source->trigger = TRUE;
201  	    }
202  	}
203  	
204  	gboolean
205  	mainloop_destroy_trigger(crm_trigger_t * source)
206  	{
207  	    GSource *gs = NULL;
208  	
209  	    if(source == NULL) {
210  	        return TRUE;
211  	    }
212  	
213  	    gs = (GSource *)source;
214  	
215  	    g_source_destroy(gs); /* Remove from mainloop, ref_count-- */
216  	    g_source_unref(gs); /* The caller no longer carries a reference to source
217  	                         *
218  	                         * At this point the source should be free'd,
219  	                         * unless we're currently processing said
220  	                         * source, in which case mainloop holds an
221  	                         * additional reference and it will be free'd
222  	                         * once our processing completes
223  	                         */
224  	    return TRUE;
225  	}
226  	
227  	// Define a custom glib source for signal handling
228  	
229  	// Data structure for custom glib source
230  	typedef struct {
231  	    crm_trigger_t trigger;      // trigger that invoked source (must be first)
232  	    void (*handler) (int sig);  // signal handler
233  	    int signal;                 // signal that was received
234  	} crm_signal_t;
235  	
236  	// Table to associate signal handlers with signal numbers
237  	static crm_signal_t *crm_signals[NSIG];
238  	
239  	/*!
240  	 * \internal
241  	 * \brief Dispatch an event from custom glib source for signals
242  	 *
243  	 * Given an signal event, clear the event trigger and call any registered
244  	 * signal handler.
245  	 *
246  	 * \param[in] source    glib source that triggered this dispatch
247  	 * \param[in] callback  (ignored)
248  	 * \param[in] userdata  (ignored)
249  	 */
250  	static gboolean
251  	crm_signal_dispatch(GSource *source, GSourceFunc callback, void *userdata)
252  	{
253  	    crm_signal_t *sig = (crm_signal_t *) source;
254  	
255  	    if(sig->signal != SIGCHLD) {
256  	        pcmk__notice("Caught '%s' signal " QB_XS " %d (%s handler)",
257  	                     strsignal(sig->signal), sig->signal,
258  	                     ((sig->handler != NULL)? "invoking" : "no"));
259  	    }
260  	
261  	    sig->trigger.trigger = FALSE;
262  	    if (sig->handler) {
263  	        sig->handler(sig->signal);
264  	    }
265  	    return TRUE;
266  	}
267  	
268  	/*!
269  	 * \internal
270  	 * \brief Handle a signal by setting a trigger for signal source
271  	 *
272  	 * \param[in] sig  Signal number that was received
273  	 *
274  	 * \note This is the true signal handler for the mainloop signal source, and
275  	 *       must be async-safe.
276  	 */
277  	static void
278  	mainloop_signal_handler(int sig)
279  	{
280  	    if (sig > 0 && sig < NSIG && crm_signals[sig] != NULL) {
281  	        mainloop_set_trigger((crm_trigger_t *) crm_signals[sig]);
282  	    }
283  	}
284  	
285  	// Functions implementing our custom glib source for signal handling
286  	static GSourceFuncs crm_signal_funcs = {
287  	    crm_trigger_prepare,
288  	    crm_trigger_check,
289  	    crm_signal_dispatch,
290  	    crm_trigger_finalize,
291  	};
292  	
293  	/*!
294  	 * \internal
295  	 * \brief Set a true signal handler
296  	 *
297  	 * signal()-like interface to sigaction()
298  	 *
299  	 * \param[in] sig       Signal number to register handler for
300  	 * \param[in] dispatch  Signal handler
301  	 *
302  	 * \return The previous value of the signal handler, or SIG_ERR on error
303  	 * \note The dispatch function must be async-safe.
304  	 */
305  	sighandler_t
306  	crm_signal_handler(int sig, sighandler_t dispatch)
307  	{
308  	    sigset_t mask;
309  	    struct sigaction sa;
310  	    struct sigaction old;
311  	
312  	    if (sigemptyset(&mask) < 0) {
313  	        pcmk__err("Could not %sset handler for signal %d: %s",
314  	                  ((dispatch == NULL)? "un" : ""), sig, strerror(errno));
315  	        return SIG_ERR;
316  	    }
317  	
318  	    memset(&sa, 0, sizeof(struct sigaction));
319  	    sa.sa_handler = dispatch;
320  	    sa.sa_flags = SA_RESTART;
321  	    sa.sa_mask = mask;
322  	
323  	    if (sigaction(sig, &sa, &old) < 0) {
324  	        pcmk__err("Could not %sset handler for signal %d: %s",
325  	                  ((dispatch == NULL)? "un" : ""), sig, strerror(errno));
326  	        return SIG_ERR;
327  	    }
328  	    return old.sa_handler;
329  	}
330  	
331  	static void
332  	mainloop_destroy_signal_entry(int sig)
333  	{
334  	    crm_signal_t *tmp = crm_signals[sig];
335  	
336  	    if (tmp != NULL) {
337  	        crm_signals[sig] = NULL;
338  	        pcmk__trace("Unregistering mainloop handler for signal %d", sig);
339  	        mainloop_destroy_trigger((crm_trigger_t *) tmp);
340  	    }
341  	}
342  	
343  	/*!
344  	 * \internal
345  	 * \brief Add a signal handler to a mainloop
346  	 *
347  	 * \param[in] sig       Signal number to handle
348  	 * \param[in] dispatch  Signal handler function (\c NULL to ignore the signal)
349  	 *
350  	 * \note The true signal handler merely sets a mainloop trigger to call this
351  	 *       dispatch function via the mainloop. Therefore, the dispatch function
352  	 *       does not need to be async-safe.
353  	 * \note The added signal handler gets freed by \c mainloop_cleanup() if it is
354  	 *       not freed manually using \c mainloop_destroy_signal().
355  	 */
356  	gboolean
357  	mainloop_add_signal(int sig, void (*dispatch) (int sig))
358  	{
359  	    GSource *source = NULL;
360  	    int priority = G_PRIORITY_HIGH - 1;
361  	
362  	    if (sig == SIGTERM) {
363  	        /* TERM is higher priority than other signals,
364  	         *   signals are higher priority than other ipc.
365  	         * Yes, minus: smaller is "higher"
366  	         */
367  	        priority--;
368  	    }
369  	
370  	    if (sig >= NSIG || sig < 0) {
371  	        pcmk__err("Signal %d is out of range", sig);
372  	        return FALSE;
373  	
374  	    } else if (crm_signals[sig] != NULL && crm_signals[sig]->handler == dispatch) {
375  	        pcmk__trace("Signal handler for %d is already installed", sig);
376  	        return TRUE;
377  	
378  	    } else if (crm_signals[sig] != NULL) {
379  	        pcmk__err("Different signal handler for %d is already installed", sig);
380  	        return FALSE;
381  	    }
382  	
383  	    pcmk__assert(sizeof(crm_signal_t) > sizeof(GSource));
384  	    source = g_source_new(&crm_signal_funcs, sizeof(crm_signal_t));
385  	
386  	    crm_signals[sig] = (crm_signal_t *) mainloop_setup_trigger(source, priority, NULL, NULL);
387  	    pcmk__assert(crm_signals[sig] != NULL);
388  	
389  	    crm_signals[sig]->handler = dispatch;
390  	    crm_signals[sig]->signal = sig;
391  	
392  	    if (crm_signal_handler(sig, mainloop_signal_handler) == SIG_ERR) {
393  	        mainloop_destroy_signal_entry(sig);
394  	        return FALSE;
395  	    }
396  	
397  	    return TRUE;
398  	}
399  	
400  	gboolean
401  	mainloop_destroy_signal(int sig)
402  	{
403  	    if (sig >= NSIG || sig < 0) {
404  	        pcmk__err("Signal %d is out of range", sig);
405  	        return FALSE;
406  	
407  	    } else if (crm_signal_handler(sig, NULL) == SIG_ERR) {
408  	        // Error already logged
409  	        return FALSE;
410  	
411  	    } else if (crm_signals[sig] == NULL) {
412  	        return TRUE;
413  	    }
414  	    mainloop_destroy_signal_entry(sig);
415  	    return TRUE;
416  	}
417  	
418  	/*!
419  	 * \internal
420  	 * \brief Free data structures used for the mainloop
421  	 *
422  	 * \todo This is incomplete. Free other data structures created in this file.
423  	 */
424  	void
425  	mainloop_cleanup(void)
426  	{
427  	    g_clear_pointer(&mainloop_children, g_hash_table_destroy);
428  	    g_clear_pointer(&gio_map, qb_array_free);
429  	
430  	    for (int sig = 0; sig < NSIG; ++sig) {
431  	        mainloop_destroy_signal_entry(sig);
432  	    }
433  	}
434  	
435  	/*
436  	 * libqb...
437  	 */
438  	struct gio_to_qb_poll {
439  	    int32_t is_used;
440  	    unsigned int source;
441  	    int32_t events;
442  	    void *data;
443  	    qb_ipcs_dispatch_fn_t fn;
444  	    enum qb_loop_priority p;
445  	};
446  	
447  	static gboolean
448  	gio_read_socket(GIOChannel * gio, GIOCondition condition, void *data)
449  	{
450  	    struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
451  	    int fd = g_io_channel_unix_get_fd(gio);
452  	
453  	    pcmk__trace("%p.%d %d", data, fd, condition);
454  	
455  	    /* if this assert get's hit, then there is a race condition between
456  	     * when we destroy a fd and when mainloop actually gives it up */
457  	    pcmk__assert(adaptor->is_used > 0);
458  	
459  	    return (adaptor->fn(fd, condition, adaptor->data) == 0);
460  	}
461  	
462  	static void
463  	gio_poll_destroy(void *data)
464  	{
465  	    struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
466  	
467  	    adaptor->is_used--;
468  	    pcmk__assert(adaptor->is_used >= 0);
469  	
470  	    if (adaptor->is_used == 0) {
471  	        pcmk__trace("Marking adaptor %p unused", adaptor);
472  	        adaptor->source = 0;
473  	    }
474  	}
475  	
476  	/*!
477  	 * \internal
478  	 * \brief Convert libqb's poll priority into GLib's one
479  	 *
480  	 * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
481  	 *
482  	 * \return  best matching GLib's priority
483  	 */
484  	static int
485  	conv_prio_libqb2glib(enum qb_loop_priority prio)
486  	{
487  	    switch (prio) {
488  	        case QB_LOOP_LOW:   return G_PRIORITY_LOW;
489  	        case QB_LOOP_HIGH:  return G_PRIORITY_HIGH;
490  	        default:            return G_PRIORITY_DEFAULT; // QB_LOOP_MED
491  	    }
492  	}
493  	
494  	/*!
495  	 * \internal
496  	 * \brief Convert libqb's poll priority to rate limiting spec
497  	 *
498  	 * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
499  	 *
500  	 * \return  best matching rate limiting spec
501  	 * \note This is the inverse of libqb's qb_ipcs_request_rate_limit().
502  	 */
503  	static enum qb_ipcs_rate_limit
504  	conv_libqb_prio2ratelimit(enum qb_loop_priority prio)
505  	{
506  	    switch (prio) {
507  	        case QB_LOOP_LOW:   return QB_IPCS_RATE_SLOW;
508  	        case QB_LOOP_HIGH:  return QB_IPCS_RATE_FAST;
509  	        default:            return QB_IPCS_RATE_NORMAL; // QB_LOOP_MED
510  	    }
511  	}
512  	
513  	static int32_t
514  	gio_poll_dispatch_update(enum qb_loop_priority p, int32_t fd, int32_t evts,
515  	                         void *data, qb_ipcs_dispatch_fn_t fn, int32_t add)
516  	{
517  	    struct gio_to_qb_poll *adaptor;
518  	    GIOChannel *channel;
519  	    int32_t res = 0;
520  	
521  	    res = qb_array_index(gio_map, fd, (void **)&adaptor);
522  	    if (res < 0) {
523  	        pcmk__err("Array lookup failed for fd=%d: %d", fd, res);
524  	        return res;
525  	    }
526  	
527  	    pcmk__trace("Adding fd=%d to mainloop as adaptor %p", fd, adaptor);
528  	
529  	    if (add && adaptor->source) {
530  	        pcmk__err("Adaptor for descriptor %d is still in-use", fd);
531  	        return -EEXIST;
532  	    }
533  	    if (!add && !adaptor->is_used) {
534  	        pcmk__err("Adaptor for descriptor %d is not in-use", fd);
535  	        return -ENOENT;
536  	    }
537  	
538  	    /* channel is created with ref_count = 1 */
539  	    channel = g_io_channel_unix_new(fd);
540  	    if (!channel) {
541  	        pcmk__err("No memory left to add fd=%d", fd);
542  	        return -ENOMEM;
543  	    }
544  	
545  	    if (adaptor->source) {
546  	        g_source_remove(adaptor->source);
547  	        adaptor->source = 0;
548  	    }
549  	
550  	    /* Because unlike the poll() API, glib doesn't tell us about HUPs by default */
551  	    evts |= (G_IO_HUP | G_IO_NVAL | G_IO_ERR);
552  	
553  	    adaptor->fn = fn;
554  	    adaptor->events = evts;
555  	    adaptor->data = data;
556  	    adaptor->p = p;
557  	    adaptor->is_used++;
558  	    adaptor->source =
559  	        g_io_add_watch_full(channel, conv_prio_libqb2glib(p), evts,
560  	                            gio_read_socket, adaptor, gio_poll_destroy);
561  	
562  	    /* Now that mainloop now holds a reference to channel,
563  	     * thanks to g_io_add_watch_full(), drop ours from g_io_channel_unix_new().
564  	     *
565  	     * This means that channel will be free'd by:
566  	     * g_main_context_dispatch()
567  	     *  -> g_source_destroy_internal()
568  	     *      -> g_source_callback_unref()
569  	     * shortly after gio_poll_destroy() completes
570  	     */
571  	    g_io_channel_unref(channel);
572  	
573  	    pcmk__trace("Added to mainloop with gsource id=%d", adaptor->source);
574  	    if (adaptor->source > 0) {
575  	        return 0;
576  	    }
577  	
578  	    return -EINVAL;
579  	}
580  	
581  	static int32_t
582  	gio_poll_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
583  	                      void *data, qb_ipcs_dispatch_fn_t fn)
584  	{
585  	    return gio_poll_dispatch_update(p, fd, evts, data, fn, QB_TRUE);
586  	}
587  	
588  	static int32_t
589  	gio_poll_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts,
590  	                      void *data, qb_ipcs_dispatch_fn_t fn)
591  	{
592  	    return gio_poll_dispatch_update(p, fd, evts, data, fn, QB_FALSE);
593  	}
594  	
595  	static int32_t
596  	gio_poll_dispatch_del(int32_t fd)
597  	{
598  	    struct gio_to_qb_poll *adaptor;
599  	
600  	    pcmk__trace("Looking for fd=%d", fd);
601  	    if (qb_array_index(gio_map, fd, (void **)&adaptor) == 0) {
602  	        if (adaptor->source) {
603  	            g_source_remove(adaptor->source);
604  	            adaptor->source = 0;
605  	        }
606  	    }
607  	    return 0;
608  	}
609  	
610  	struct qb_ipcs_poll_handlers gio_poll_funcs = {
611  	    .job_add = NULL,
612  	    .dispatch_add = gio_poll_dispatch_add,
613  	    .dispatch_mod = gio_poll_dispatch_mod,
614  	    .dispatch_del = gio_poll_dispatch_del,
615  	};
616  	
617  	qb_ipcs_service_t *
618  	mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
619  	                        struct qb_ipcs_service_handlers *callbacks)
620  	{
621  	    return mainloop_add_ipc_server_with_prio(name, type, callbacks, QB_LOOP_MED);
622  	}
623  	
624  	qb_ipcs_service_t *
625  	mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type,
626  	                                  struct qb_ipcs_service_handlers *callbacks,
627  	                                  enum qb_loop_priority prio)
628  	{
629  	    int rc = 0;
630  	    qb_ipcs_service_t *server = NULL;
631  	
632  	    if (gio_map == NULL) {
633  	        gio_map = qb_array_create_2(64, sizeof(struct gio_to_qb_poll), 1);
634  	    }
635  	
636  	    server = qb_ipcs_create(name, 0, QB_IPC_SHM, callbacks);
637  	
638  	    if (server == NULL) {
639  	        pcmk__err("Could not create %s IPC server: %s (%d)", name,
640  	                  pcmk_rc_str(errno), errno);
641  	        return NULL;
642  	    }
643  	
644  	    if (prio != QB_LOOP_MED) {
645  	        qb_ipcs_request_rate_limit(server, conv_libqb_prio2ratelimit(prio));
646  	    }
647  	
648  	    // Enforce a minimum IPC buffer size on all clients
649  	    qb_ipcs_enforce_buffer_size(server, crm_ipc_default_buffer_size());
650  	    qb_ipcs_poll_handlers_set(server, &gio_poll_funcs);
651  	
652  	    rc = qb_ipcs_run(server);
653  	    if (rc < 0) {
654  	        pcmk__err("Could not start %s IPC server: %s (%d)", name,
655  	                  pcmk_strerror(rc), rc);
656  	        return NULL; // qb_ipcs_run() destroys server on failure
657  	    }
658  	
659  	    return server;
660  	}
661  	
662  	void
663  	mainloop_del_ipc_server(qb_ipcs_service_t * server)
664  	{
665  	    if (server) {
666  	        qb_ipcs_destroy(server);
667  	    }
668  	}
669  	
670  	/*!
671  	 * \internal
672  	 * \brief I/O watch callback function (GIOFunc)
673  	 *
674  	 * \param[in] gio        I/O channel being watched
675  	 * \param[in] condition  I/O condition satisfied
676  	 * \param[in] data       User data passed when source was created
677  	 *
678  	 * \return G_SOURCE_REMOVE to remove source, G_SOURCE_CONTINUE to keep it
679  	 */
680  	static gboolean
681  	mainloop_gio_callback(GIOChannel *gio, GIOCondition condition, void *data)
682  	{
683  	    gboolean rc = G_SOURCE_CONTINUE;
684  	    mainloop_io_t *client = data;
685  	
686  	    pcmk__assert(client->fd == g_io_channel_unix_get_fd(gio));
687  	
688  	    if (condition & G_IO_IN) {
689  	        if (client->ipc) {
690  	            long read_rc = 0L;
691  	            int max = 10;
692  	
693  	            do {
694  	                read_rc = crm_ipc_read(client->ipc);
695  	                if (read_rc <= 0) {
696  	                    pcmk__trace("Could not read IPC message from %s: %s (%ld)",
697  	                                client->name, pcmk_strerror(read_rc), read_rc);
698  	
699  	                    if (read_rc == -EAGAIN) {
700  	                        continue;
701  	                    }
702  	
703  	                } else if (client->dispatch_fn_ipc) {
704  	                    const char *buffer = crm_ipc_buffer(client->ipc);
705  	
706  	                    pcmk__trace("New %ld-byte IPC message from %s after I/O "
707  	                                "condition %d",
708  	                                read_rc, client->name, (int) condition);
709  	                    if (client->dispatch_fn_ipc(buffer, read_rc, client->userdata) < 0) {
710  	                        pcmk__trace("Connection to %s no longer required",
711  	                                    client->name);
712  	                        rc = G_SOURCE_REMOVE;
713  	                    }
714  	                }
715  	
716  	                pcmk__ipc_free_client_buffer(client->ipc);
717  	
718  	            } while ((rc == G_SOURCE_CONTINUE) && (--max > 0)
719  	                      && ((read_rc > 0) || (read_rc == -EAGAIN)));
720  	
721  	        } else {
722  	            pcmk__trace("New I/O event for %s after I/O condition %d",
723  	                        client->name, (int) condition);
724  	            if (client->dispatch_fn_io) {
725  	                if (client->dispatch_fn_io(client->userdata) < 0) {
726  	                    pcmk__trace("Connection to %s no longer required",
727  	                                client->name);
728  	                    rc = G_SOURCE_REMOVE;
729  	                }
730  	            }
731  	        }
732  	    }
733  	
734  	    if (client->ipc && !crm_ipc_connected(client->ipc)) {
735  	        pcmk__err("Connection to %s closed " QB_XS " client=%p condition=%d",
736  	                  client->name, client, condition);
737  	        rc = G_SOURCE_REMOVE;
738  	
739  	    } else if (condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR)) {
740  	        pcmk__trace("The connection %s[%p] has been closed (I/O condition=%d)",
741  	                    client->name, client, condition);
742  	        rc = G_SOURCE_REMOVE;
743  	
744  	    } else if ((condition & G_IO_IN) == 0) {
745  	        /*
746  	           #define      GLIB_SYSDEF_POLLIN     =1
747  	           #define      GLIB_SYSDEF_POLLPRI    =2
748  	           #define      GLIB_SYSDEF_POLLOUT    =4
749  	           #define      GLIB_SYSDEF_POLLERR    =8
750  	           #define      GLIB_SYSDEF_POLLHUP    =16
751  	           #define      GLIB_SYSDEF_POLLNVAL   =32
752  	
753  	           typedef enum
754  	           {
755  	           G_IO_IN      GLIB_SYSDEF_POLLIN,
756  	           G_IO_OUT     GLIB_SYSDEF_POLLOUT,
757  	           G_IO_PRI     GLIB_SYSDEF_POLLPRI,
758  	           G_IO_ERR     GLIB_SYSDEF_POLLERR,
759  	           G_IO_HUP     GLIB_SYSDEF_POLLHUP,
760  	           G_IO_NVAL    GLIB_SYSDEF_POLLNVAL
761  	           } GIOCondition;
762  	
763  	           A bitwise combination representing a condition to watch for on an event source.
764  	
765  	           G_IO_IN      There is data to read.
766  	           G_IO_OUT     Data can be written (without blocking).
767  	           G_IO_PRI     There is urgent data to read.
768  	           G_IO_ERR     Error condition.
769  	           G_IO_HUP     Hung up (the connection has been broken, usually for pipes and sockets).
770  	           G_IO_NVAL    Invalid request. The file descriptor is not open.
771  	         */
772  	        pcmk__err("Strange condition: %d", condition);
773  	    }
774  	
775  	    /* G_SOURCE_REMOVE results in mainloop_gio_destroy() being called
776  	     * just before the source is removed from mainloop
777  	     */
778  	    return rc;
779  	}
780  	
781  	static void
(3) Event deallocator: Deallocator for "struct mainloop_io_s".
Also see events: [allocation][allocation]
782  	mainloop_gio_destroy(void *c)
783  	{
784  	    mainloop_io_t *client = c;
785  	    char *c_name = strdup(client->name);
786  	
787  	    /* client->source is valid but about to be destroyed (ref_count == 0) in gmain.c
788  	     * client->channel will still have ref_count > 0... should be == 1
789  	     */
790  	    pcmk__trace("Destroying client %s[%p]", c_name, c);
791  	
792  	    if (client->ipc) {
793  	        crm_ipc_close(client->ipc);
794  	    }
795  	
796  	    if (client->destroy_fn) {
797  	        void (*destroy_fn)(void *userdata) = client->destroy_fn;
798  	
799  	        client->destroy_fn = NULL;
800  	        destroy_fn(client->userdata);
801  	    }
802  	
803  	    if (client->ipc) {
804  	        crm_ipc_t *ipc = client->ipc;
805  	
806  	        client->ipc = NULL;
807  	        crm_ipc_destroy(ipc);
808  	    }
809  	
810  	    pcmk__trace("Destroyed client %s[%p]", c_name, c);
811  	
812  	    free(client->name);
813  	    free(client);
814  	
815  	    free(c_name);
816  	}
817  	
818  	/*!
819  	 * \brief Connect to IPC and add it as a main loop source
820  	 *
821  	 * \param[in,out] ipc        IPC connection to add
822  	 * \param[in]     priority   Event source priority to use for connection
823  	 * \param[in]     userdata   Data to register with callbacks
824  	 * \param[in]     callbacks  Dispatch and destroy callbacks for connection
825  	 * \param[out]    source     Newly allocated event source
826  	 *
827  	 * \return Standard Pacemaker return code
828  	 *
829  	 * \note On failure, the caller is still responsible for ipc. On success, the
830  	 *       caller should call mainloop_del_ipc_client() when source is no longer
831  	 *       needed, which will lead to the disconnection of the IPC later in the
832  	 *       main loop if it is connected. However the IPC disconnects,
833  	 *       mainloop_gio_destroy() will free ipc and source after calling the
834  	 *       destroy callback.
835  	 */
836  	int
837  	pcmk__add_mainloop_ipc(crm_ipc_t *ipc, int priority, void *userdata,
838  	                       const struct ipc_client_callbacks *callbacks,
839  	                       mainloop_io_t **source)
840  	{
841  	    int rc = pcmk_rc_ok;
842  	    int fd = -1;
843  	    const char *ipc_name = NULL;
844  	
845  	    CRM_CHECK((ipc != NULL) && (callbacks != NULL), return EINVAL);
846  	
847  	    ipc_name = pcmk__s(crm_ipc_name(ipc), "Pacemaker");
848  	    rc = pcmk__connect_generic_ipc(ipc);
849  	    if (rc != pcmk_rc_ok) {
850  	        pcmk__debug("Connection to %s failed: %s", ipc_name, pcmk_rc_str(rc));
851  	        return rc;
852  	    }
853  	
854  	    rc = pcmk__ipc_fd(ipc, &fd);
855  	    if (rc != pcmk_rc_ok) {
856  	        pcmk__debug("Could not obtain file descriptor for %s IPC: %s", ipc_name,
857  	                    pcmk_rc_str(rc));
858  	        crm_ipc_close(ipc);
859  	        return rc;
860  	    }
861  	
862  	    *source = mainloop_add_fd(ipc_name, priority, fd, userdata, NULL);
863  	    if (*source == NULL) {
864  	        rc = errno;
865  	        crm_ipc_close(ipc);
866  	        return rc;
867  	    }
868  	
869  	    (*source)->ipc = ipc;
870  	    (*source)->destroy_fn = callbacks->destroy;
871  	    (*source)->dispatch_fn_ipc = callbacks->dispatch;
872  	    return pcmk_rc_ok;
873  	}
874  	
875  	/*!
876  	 * \brief Get period for mainloop timer
877  	 *
878  	 * \param[in]  timer      Timer
879  	 *
880  	 * \return Period in ms
881  	 */
882  	unsigned int
883  	pcmk__mainloop_timer_get_period(const mainloop_timer_t *timer)
884  	{
885  	    if (timer) {
886  	        return timer->period_ms;
887  	    }
888  	    return 0;
889  	}
890  	
891  	mainloop_io_t *
892  	mainloop_add_ipc_client(const char *name, int priority, size_t max_size,
893  	                        void *userdata, struct ipc_client_callbacks *callbacks)
894  	{
895  	    crm_ipc_t *ipc = crm_ipc_new(name, 0);
896  	    mainloop_io_t *source = NULL;
897  	    int rc = pcmk__add_mainloop_ipc(ipc, priority, userdata, callbacks,
898  	                                    &source);
899  	
900  	    if (rc != pcmk_rc_ok) {
901  	        if (crm_log_level == PCMK__LOG_STDOUT) {
902  	            fprintf(stderr, "Connection to %s failed: %s",
903  	                    name, pcmk_rc_str(rc));
904  	        }
905  	        crm_ipc_destroy(ipc);
906  	        if (rc > 0) {
907  	            errno = rc;
908  	        } else {
909  	            errno = ENOTCONN;
910  	        }
911  	        return NULL;
912  	    }
913  	    return source;
914  	}
915  	
916  	void
917  	mainloop_del_ipc_client(mainloop_io_t * client)
918  	{
919  	    mainloop_del_fd(client);
920  	}
921  	
922  	crm_ipc_t *
923  	mainloop_get_ipc_client(mainloop_io_t * client)
924  	{
925  	    if (client) {
926  	        return client->ipc;
927  	    }
928  	    return NULL;
929  	}
930  	
931  	mainloop_io_t *
932  	mainloop_add_fd(const char *name, int priority, int fd, void *userdata,
933  	                struct mainloop_fd_callbacks * callbacks)
934  	{
935  	    mainloop_io_t *client = NULL;
936  	    const GIOCondition condition = G_IO_IN|G_IO_HUP|G_IO_NVAL|G_IO_ERR;
937  	
938  	    if (fd < 0) {
939  	        errno = EINVAL;
940  	        return NULL;
941  	    }
942  	
943  	    client = pcmk__assert_alloc(1, sizeof(mainloop_io_t));
944  	    client->name = pcmk__str_copy(name);
945  	    client->userdata = userdata;
946  	
947  	    if (callbacks != NULL) {
948  	        client->destroy_fn = callbacks->destroy;
949  	        client->dispatch_fn_io = callbacks->dispatch;
950  	    }
951  	
952  	    client->fd = fd;
CID (unavailable; MK=b13c37cce9c4cfa0c98303204ab57333) (#1 of 1): Resource not released (INCOMPLETE_DEALLOCATOR):
(1) Event allocation: Memory is allocated.
(2) Event allocation: The field "client->channel" is allocated, but not released in the identified deallocator.
Also see events: [deallocator]
953  	    client->channel = g_io_channel_unix_new(fd);
954  	    client->source = g_io_add_watch_full(client->channel, priority, condition,
955  	                                         mainloop_gio_callback, client,
956  	                                         mainloop_gio_destroy);
957  	
958  	    /* Now that mainloop now holds a reference to channel, thanks to
959  	     * g_io_add_watch_full(), drop ours from g_io_channel_unix_new().
960  	     *
961  	     * This means that channel will be free'd by:
962  	     * g_main_context_dispatch() or g_source_remove()
963  	     *  -> g_source_destroy_internal()
964  	     *      -> g_source_callback_unref()
965  	     * shortly after mainloop_gio_destroy() completes
966  	     */
967  	    g_io_channel_unref(client->channel);
968  	
969  	    pcmk__trace("Added connection %d for %s[%p].%d", client->source,
970  	                client->name, client, fd);
971  	    return client;
972  	}
973  	
974  	void
975  	mainloop_del_fd(mainloop_io_t *client)
976  	{
977  	    if ((client == NULL) || (client->source == 0)) {
978  	        return;
979  	    }
980  	
981  	    pcmk__trace("Removing client %s[%p]", client->name, client);
982  	
983  	    /* g_source_remove() marks the source as destroyed, unsets the source
984  	     * callback (mainloop_gio_callback()), and destroys the callback data (the
985  	     * client) via the notify function (mainloop_gio_destroy()). We can rely on
986  	     * mainloop_gio_callback() not getting called again for this source, and on
987  	     * the client being destroyed.
988  	     */
989  	    g_source_remove(client->source);
990  	}
991  	
992  	pid_t
993  	mainloop_child_pid(mainloop_child_t * child)
994  	{
995  	    return child->pid;
996  	}
997  	
998  	const char *
999  	mainloop_child_name(mainloop_child_t * child)
1000 	{
1001 	    return child->desc;
1002 	}
1003 	
1004 	int
1005 	mainloop_child_timeout(mainloop_child_t * child)
1006 	{
1007 	    return child->timeout;
1008 	}
1009 	
1010 	void *
1011 	mainloop_child_userdata(mainloop_child_t * child)
1012 	{
1013 	    return child->privatedata;
1014 	}
1015 	
1016 	void
1017 	mainloop_clear_child_userdata(mainloop_child_t * child)
1018 	{
1019 	    child->privatedata = NULL;
1020 	}
1021 	
1022 	static int
1023 	child_kill_helper(const mainloop_child_t *child)
1024 	{
1025 	    int rc = 0;
1026 	
1027 	    if (pcmk__is_set(child->flags, mainloop_leave_pid_group)) {
1028 	        pcmk__debug("Killing PID %lld only. Leaving its process group intact.",
1029 	                    (long long) child->pid);
1030 	        rc = kill(child->pid, SIGKILL);
1031 	
1032 	    } else {
1033 	        pcmk__debug("Killing PID %lld's entire process group",
1034 	                    (long long) child->pid);
1035 	        rc = kill(-child->pid, SIGKILL);
1036 	    }
1037 	
1038 	    if (rc == 0) {
1039 	        return pcmk_rc_ok;
1040 	    }
1041 	
1042 	    rc = errno;
1043 	    if (rc == ESRCH) {
1044 	        return rc;
1045 	    }
1046 	
1047 	    pcmk__err("kill(%lld, KILL) failed: %s", (long long) child->pid,
1048 	              strerror(rc));
1049 	    return rc;
1050 	}
1051 	
1052 	static gboolean
1053 	child_timeout_callback(void *p)
1054 	{
1055 	    mainloop_child_t *child = p;
1056 	    int rc = pcmk_rc_ok;
1057 	
1058 	    child->timerid = 0;
1059 	    if (child->timeout) {
1060 	        pcmk__warn("%s process (PID %lld) will not die!", child->desc,
1061 	                   (long long) child->pid);
1062 	        return FALSE;
1063 	    }
1064 	
1065 	    rc = child_kill_helper(child);
1066 	    if (rc == ESRCH) {
1067 	        /* Nothing left to do. pid doesn't exist */
1068 	        return FALSE;
1069 	    }
1070 	
1071 	    child->timeout = TRUE;
1072 	    pcmk__debug("%s process (PID %lld) timed out", child->desc,
1073 	                (long long) child->pid);
1074 	
1075 	    child->timerid = pcmk__create_timer(5000, child_timeout_callback, child);
1076 	    return FALSE;
1077 	}
1078 	
1079 	static bool
1080 	child_waitpid(mainloop_child_t *child, int flags)
1081 	{
1082 	    int rc = 0;
1083 	    int core = 0;
1084 	    int signo = 0;
1085 	    int status = 0;
1086 	    int exitcode = 0;
1087 	
1088 	    rc = waitpid(child->pid, &status, flags);
1089 	
1090 	    if (rc == 0) { // WNOHANG in flags, and child status is not available
1091 	        pcmk__trace("Child process %lld (%s) still active",
1092 	                    (long long) child->pid, child->desc);
1093 	        return false;
1094 	    }
1095 	
1096 	    if (rc != child->pid) {
1097 	        /* According to POSIX, possible conditions:
1098 	         * - child->pid was non-positive (process group or any child),
1099 	         *   and rc is specific child
1100 	         * - errno ECHILD (pid does not exist or is not child)
1101 	         * - errno EINVAL (invalid flags)
1102 	         * - errno EINTR (caller interrupted by signal)
1103 	         *
1104 	         * @TODO Handle these cases more specifically.
1105 	         */
1106 	        signo = SIGCHLD;
1107 	        exitcode = 1;
1108 	        pcmk__notice("Wait for child process %lld (%s) interrupted: %s",
1109 	                     (long long) child->pid, child->desc, strerror(errno));
1110 	
1111 	    } else if (WIFEXITED(status)) {
1112 	        exitcode = WEXITSTATUS(status);
1113 	        pcmk__trace("Child process %lld (%s) exited with status %d",
1114 	                    (long long) child->pid, child->desc, exitcode);
1115 	
1116 	    } else if (WIFSIGNALED(status)) {
1117 	        signo = WTERMSIG(status);
1118 	        pcmk__trace("Child process %lld (%s) exited with signal %d (%s)",
1119 	                    (long long) child->pid, child->desc, signo,
1120 	                    strsignal(signo));
1121 	
1122 	#ifdef WCOREDUMP // AIX, SunOS, maybe others
1123 	    } else if (WCOREDUMP(status)) {
1124 	        core = 1;
1125 	        pcmk__err("Child process %lld (%s) dumped core", (long long) child->pid,
1126 	                  child->desc);
1127 	#endif
1128 	
1129 	    } else { // flags must contain WUNTRACED and/or WCONTINUED to reach this
1130 	        pcmk__trace("Child process %lld (%s) stopped or continued",
1131 	                    (long long) child->pid, child->desc);
1132 	        return false;
1133 	    }
1134 	
1135 	    if (child->exit_fn != NULL) {
1136 	        child->exit_fn(child, core, signo, exitcode);
1137 	    }
1138 	
1139 	    return true;
1140 	}
1141 	
1142 	static gboolean
1143 	child_waitpid_no_hang(void *key, void *value, void *user_data)
1144 	{
1145 	    mainloop_child_t *child = value;
1146 	
1147 	    if (!child_waitpid(child, WNOHANG)) {
1148 	        return FALSE;
1149 	    }
1150 	
1151 	    pcmk__trace("Removing completed process %lld from child table",
1152 	                (long long) child->pid);
1153 	    return TRUE;
1154 	}
1155 	
1156 	static void
1157 	child_death_dispatch(int signal)
1158 	{
1159 	    if (mainloop_children == NULL) {
1160 	        return;
1161 	    }
1162 	
1163 	    g_hash_table_foreach_remove(mainloop_children, child_waitpid_no_hang, NULL);
1164 	}
1165 	
1166 	static gboolean
1167 	child_signal_init(void *p)
1168 	{
1169 	    pcmk__trace("Installed SIGCHLD handler");
1170 	    /* Do NOT use g_child_watch_add() and friends, they rely on pthreads */
1171 	    mainloop_add_signal(SIGCHLD, child_death_dispatch);
1172 	
1173 	    /* In case they terminated before the signal handler was installed */
1174 	    child_death_dispatch(SIGCHLD);
1175 	    return FALSE;
1176 	}
1177 	
1178 	gboolean
1179 	mainloop_child_kill(pid_t pid)
1180 	{
1181 	    /* It is impossible to block SIGKILL. This allows us to call waitpid()
1182 	     * without the WNOHANG flag.
1183 	     */
1184 	    int waitflags = 0;
1185 	    int rc = pcmk_rc_ok;
1186 	    char *pid_s = NULL;
1187 	    mainloop_child_t *child = NULL;
1188 	    gboolean killed = FALSE;
1189 	
1190 	    if (mainloop_children == NULL) {
1191 	        // We're not tracking any children, so don't kill this PID
1192 	        goto done;
1193 	    }
1194 	
1195 	    pid_s = pcmk__assert_asprintf("%lld", (long long) pid);
1196 	    child = g_hash_table_lookup(mainloop_children, pid_s);
1197 	
1198 	    if (child == NULL) {
1199 	        // We're not tracking a child with this PID, so don't kill it
1200 	        goto done;
1201 	    }
1202 	
1203 	    rc = child_kill_helper(child);
1204 	    if (rc == ESRCH) {
1205 	        /* kill() didn't find the PID. Assume this means the process is in some
1206 	         * intermediate stage of exiting. Wait until we get SIGCHLD and let
1207 	         * the handler clean it up as normal, so that we get the correct return
1208 	         * code/status. The blocking alternative would be to call
1209 	         * child_waitpid(child, 0).
1210 	         *
1211 	         * Treat this as success in the meantime.
1212 	         */
1213 	        pcmk__trace("Waiting for signal that child process %lld completed",
1214 	                    (long long) child->pid);
1215 	        killed = TRUE;
1216 	        goto done;
1217 	    }
1218 	
1219 	    if (rc != pcmk_rc_ok) {
1220 	        /* If kill() failed for some other reason, set the WNOHANG flag, since
1221 	         * we can't be certain what happened.
1222 	         */
1223 	        waitflags = WNOHANG;
1224 	    }
1225 	
1226 	    if (!child_waitpid(child, waitflags)) {
1227 	        /* waitpid() didn't find the child. This shouldn't happen if kill()
1228 	         * succeeded. In any case, there's no obviously good way to proceed.
1229 	         * Treat this as a failure.
1230 	         *
1231 	         * @TODO Should we call the child's exit_fn with a failure here, and/or
1232 	         * free the mainloop_child_t? We can hope that we successfully wait on
1233 	         * it in response to a SIGCHLD that comes later. But we might just never
1234 	         * do anything with this child again.
1235 	         *
1236 	         * @TODO Consider using GSubprocess for all subprocess tracking.
1237 	         */
1238 	        goto done;
1239 	    }
1240 	
1241 	    g_hash_table_remove(mainloop_children, pid_s);
1242 	    killed = TRUE;
1243 	
1244 	done:
1245 	    free(pid_s);
1246 	    return killed;
1247 	}
1248 	
1249 	/* Create/Log a new tracked process
1250 	 * To track a process group, use -pid
1251 	 *
1252 	 * Newly created child will be freed by mainloop_cleanup(), if not sooner.
1253 	 *
1254 	 * @TODO Using a non-positive pid (i.e. any child, or process group) would
1255 	 *       likely not be useful since we will free the child after the first
1256 	 *       completed process.
1257 	 */
1258 	void
1259 	mainloop_child_add_with_flags(pid_t pid, int timeout, const char *desc,
1260 	                              void *privatedata,
1261 	                              enum mainloop_child_flags flags,
1262 	                              pcmk__mainloop_child_exit_fn_t exit_fn)
1263 	{
1264 	    static bool need_init = TRUE;
1265 	    bool is_new = false;
1266 	    mainloop_child_t *child = pcmk__assert_alloc(1, sizeof(mainloop_child_t));
1267 	
1268 	    child->pid = pid;
1269 	    child->timerid = 0;
1270 	    child->timeout = FALSE;
1271 	    child->privatedata = privatedata;
1272 	    child->exit_fn = exit_fn;
1273 	    child->flags = flags;
1274 	    child->desc = pcmk__str_copy(desc);
1275 	
1276 	    if (timeout) {
1277 	        child->timerid = pcmk__create_timer(timeout, child_timeout_callback, child);
1278 	    }
1279 	
1280 	    if (mainloop_children == NULL) {
1281 	        mainloop_children = pcmk__strkey_table(free,
1282 	                                               (GDestroyNotify) child_free);
1283 	    }
1284 	
1285 	    is_new = g_hash_table_insert(mainloop_children,
1286 	                                 pcmk__assert_asprintf("%lld", (long long) pid),
1287 	                                 child);
1288 	
1289 	    // It should be impossible to have this PID in mainloop_children already
1290 	    CRM_LOG_ASSERT(is_new);
1291 	
1292 	    if(need_init) {
1293 	        need_init = FALSE;
1294 	        /* SIGCHLD processing has to be invoked from mainloop.
1295 	         * We do not want it to be possible to both add a child pid
1296 	         * to mainloop, and have the pid's exit callback invoked within
1297 	         * the same callstack. */
1298 	        pcmk__create_timer(1, child_signal_init, NULL);
1299 	    }
1300 	}
1301 	
1302 	// Newly created child will be freed by mainloop_cleanup(), if not sooner
1303 	void
1304 	mainloop_child_add(pid_t pid, int timeout, const char *desc, void *privatedata,
1305 	                   pcmk__mainloop_child_exit_fn_t exit_fn)
1306 	{
1307 	    mainloop_child_add_with_flags(pid, timeout, desc, privatedata, 0, exit_fn);
1308 	}
1309 	
1310 	static gboolean
1311 	mainloop_timer_cb(void *user_data)
1312 	{
1313 	    int id = 0;
1314 	    bool repeat = FALSE;
1315 	    struct mainloop_timer_s *t = user_data;
1316 	
1317 	    pcmk__assert(t != NULL);
1318 	
1319 	    id = t->id;
1320 	    t->id = 0; /* Ensure it's unset during callbacks so that
1321 	                * mainloop_timer_running() works as expected
1322 	                */
1323 	
1324 	    if(t->cb) {
1325 	        pcmk__trace("Invoking callbacks for timer %s", t->name);
1326 	        repeat = t->repeat;
1327 	        if(t->cb(t->userdata) == FALSE) {
1328 	            pcmk__trace("Timer %s complete", t->name);
1329 	            repeat = FALSE;
1330 	        }
1331 	    }
1332 	
1333 	    if(repeat) {
1334 	        /* Restore if repeating */
1335 	        t->id = id;
1336 	    }
1337 	
1338 	    return repeat;
1339 	}
1340 	
1341 	bool
1342 	mainloop_timer_running(mainloop_timer_t *t)
1343 	{
1344 	    if(t && t->id != 0) {
1345 	        return TRUE;
1346 	    }
1347 	    return FALSE;
1348 	}
1349 	
1350 	void
1351 	mainloop_timer_start(mainloop_timer_t *t)
1352 	{
1353 	    mainloop_timer_stop(t);
1354 	    if(t && t->period_ms > 0) {
1355 	        pcmk__trace("Starting timer %s", t->name);
1356 	        t->id = pcmk__create_timer(t->period_ms, mainloop_timer_cb, t);
1357 	    }
1358 	}
1359 	
1360 	void
1361 	mainloop_timer_stop(mainloop_timer_t *t)
1362 	{
1363 	    if(t && t->id != 0) {
1364 	        pcmk__trace("Stopping timer %s", t->name);
1365 	        g_source_remove(t->id);
1366 	        t->id = 0;
1367 	    }
1368 	}
1369 	
1370 	unsigned int
1371 	mainloop_timer_set_period(mainloop_timer_t *t, unsigned int period_ms)
1372 	{
1373 	    unsigned int last = 0;
1374 	
1375 	    if(t) {
1376 	        last = t->period_ms;
1377 	        t->period_ms = period_ms;
1378 	    }
1379 	
1380 	    if(t && t->id != 0 && last != t->period_ms) {
1381 	        mainloop_timer_start(t);
1382 	    }
1383 	    return last;
1384 	}
1385 	
1386 	mainloop_timer_t *
1387 	mainloop_timer_add(const char *name, unsigned int period_ms, bool repeat,
1388 	                   GSourceFunc cb, void *userdata)
1389 	{
1390 	    mainloop_timer_t *t = pcmk__assert_alloc(1, sizeof(mainloop_timer_t));
1391 	
1392 	    if (name != NULL) {
1393 	        t->name = pcmk__assert_asprintf("%s-%u-%d", name, period_ms, repeat);
1394 	    } else {
1395 	        t->name = pcmk__assert_asprintf("%p-%u-%d", t, period_ms, repeat);
1396 	    }
1397 	    t->id = 0;
1398 	    t->period_ms = period_ms;
1399 	    t->repeat = repeat;
1400 	    t->cb = cb;
1401 	    t->userdata = userdata;
1402 	    pcmk__trace("Created timer %s with %p %p", t->name, userdata, t->userdata);
1403 	    return t;
1404 	}
1405 	
1406 	void
1407 	mainloop_timer_del(mainloop_timer_t *t)
1408 	{
1409 	    if(t) {
1410 	        pcmk__trace("Destroying timer %s", t->name);
1411 	        mainloop_timer_stop(t);
1412 	        free(t->name);
1413 	        free(t);
1414 	    }
1415 	}
1416 	
1417 	/*
1418 	 * Helpers to make sure certain events aren't lost at shutdown
1419 	 */
1420 	
1421 	static gboolean
1422 	drain_timeout_cb(void *user_data)
1423 	{
1424 	    bool *timeout_popped = (bool*) user_data;
1425 	
1426 	    *timeout_popped = TRUE;
1427 	    return FALSE;
1428 	}
1429 	
1430 	/*!
1431 	 * \brief Drain some remaining main loop events then quit it
1432 	 *
1433 	 * \param[in,out] mloop  Main loop to drain and quit
1434 	 * \param[in]     n      Drain up to this many pending events
1435 	 */
1436 	void
1437 	pcmk_quit_main_loop(GMainLoop *mloop, unsigned int n)
1438 	{
1439 	    if ((mloop != NULL) && g_main_loop_is_running(mloop)) {
1440 	        GMainContext *ctx = g_main_loop_get_context(mloop);
1441 	
1442 	        /* Drain up to n events in case some memory clean-up is pending
1443 	         * (helpful to reduce noise in valgrind output).
1444 	         */
1445 	        for (int i = 0; (i < n) && g_main_context_pending(ctx); ++i) {
1446 	            g_main_context_dispatch(ctx);
1447 	        }
1448 	        g_main_loop_quit(mloop);
1449 	    }
1450 	}
1451 	
1452 	/*!
1453 	 * \brief Process main loop events while a certain condition is met
1454 	 *
1455 	 * \param[in,out] mloop     Main loop to process
1456 	 * \param[in]     timer_ms  Don't process longer than this amount of time
1457 	 * \param[in]     check     Function that returns true if events should be
1458 	 *                          processed
1459 	 *
1460 	 * \note This function is intended to be called at shutdown if certain important
1461 	 *       events should not be missed. The caller would likely quit the main loop
1462 	 *       or exit after calling this function. The check() function will be
1463 	 *       passed the remaining timeout in milliseconds.
1464 	 */
1465 	void
1466 	pcmk_drain_main_loop(GMainLoop *mloop, unsigned int timer_ms,
1467 	                     bool (*check)(unsigned int))
1468 	{
1469 	    bool timeout_popped = FALSE;
1470 	    unsigned int timer = 0;
1471 	    GMainContext *ctx = NULL;
1472 	
1473 	    CRM_CHECK(mloop && check, return);
1474 	
1475 	    ctx = g_main_loop_get_context(mloop);
1476 	    if (ctx) {
1477 	        time_t start_time = time(NULL);
1478 	
1479 	        timer = pcmk__create_timer(timer_ms, drain_timeout_cb, &timeout_popped);
1480 	        while (!timeout_popped
1481 	               && check(timer_ms - (time(NULL) - start_time) * 1000)) {
1482 	            g_main_context_iteration(ctx, TRUE);
1483 	        }
1484 	    }
1485 	    if (!timeout_popped && (timer > 0)) {
1486 	        g_source_remove(timer);
1487 	    }
1488 	}
1489