Coverage Report

Created: 2026-10-30 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pacemaker/lib/common/mainloop.c
Line
Count
Source
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 <errno.h>                  // errno, ESRCH, etc.
13
#include <signal.h>                 // sigaction, NSIG, SIG_ERR
14
#include <stdbool.h>                // bool, false, true
15
#include <stdint.h>                 // int32_t
16
#include <stdio.h>                  // fprintf, stderr
17
#include <stdlib.h>                 // free
18
#include <string.h>                 // memset, strerror, strsignal
19
#include <sys/types.h>              // pid_t
20
#include <sys/wait.h>               // waitpid, WNOHANG, etc.
21
#include <time.h>                   // time
22
23
#include <glib.h>                   // g_*, G_*, etc.
24
#include <qb/qbarray.h>             // qb_array_*
25
#include <qb/qbdefs.h>              // QB_FALSE, QB_TRUE
26
#include <qb/qbipc_common.h>        // qb_ipc_type
27
#include <qb/qbipcs.h>              // qb_ipcs_*
28
#include <qb/qblog.h>               // QB_XS
29
#include <qb/qbloop.h>              // qb_loop_priority
30
31
#include <crm/common/ipc.h>         // crm_ipc_*
32
#include <crm/common/logging.h>     // crm_log_level, CRM_CHECK
33
#include <crm/common/mainloop.h>    // mainloop_*
34
#include <crm/common/results.h>     // pcmk_rc_*, pcmk_strerror
35
36
struct trigger_s {
37
    GSource source;
38
    bool running;
39
    bool trigger;
40
    void *user_data;
41
    unsigned int id;
42
};
43
44
static GList *child_list = NULL;
45
static qb_array_t *gio_map = NULL;
46
47
static gboolean
48
crm_trigger_prepare(GSource *source, int *timeout)
49
0
{
50
0
    crm_trigger_t *trig = (crm_trigger_t *) source;
51
52
    /* cluster-glue's FD and IPC related sources make use of
53
     * g_source_add_poll() but do not set a timeout in their prepare
54
     * functions
55
     *
56
     * This means mainloop's poll() will block until an event for one
57
     * of these sources occurs - any /other/ type of source, such as
58
     * this one or g_idle_*, that doesn't use g_source_add_poll() is
59
     * S-O-L and won't be processed until there is something fd-based
60
     * happens.
61
     *
62
     * Luckily the timeout we can set here affects all sources and
63
     * puts an upper limit on how long poll() can take.
64
     *
65
     * So unconditionally set a small-ish timeout, not too small that
66
     * we're in constant motion, which will act as an upper bound on
67
     * how long the signal handling might be delayed for.
68
     */
69
0
    *timeout = 500;             /* Timeout in ms */
70
71
0
    return trig->trigger;
72
0
}
73
74
static gboolean
75
crm_trigger_check(GSource * source)
76
0
{
77
0
    crm_trigger_t *trig = (crm_trigger_t *) source;
78
79
0
    return trig->trigger;
80
0
}
81
82
/*!
83
 * \internal
84
 * \brief GSource dispatch function for crm_trigger_t
85
 *
86
 * \param[in] source        crm_trigger_t being dispatched
87
 * \param[in] callback      Callback passed at source creation
88
 * \param[in,out] userdata  User data passed at source creation
89
 *
90
 * \return G_SOURCE_REMOVE to remove source, G_SOURCE_CONTINUE to keep it
91
 */
92
static gboolean
93
crm_trigger_dispatch(GSource *source, GSourceFunc callback, void *userdata)
94
0
{
95
0
    gboolean rc = G_SOURCE_CONTINUE;
96
0
    crm_trigger_t *trig = (crm_trigger_t *) source;
97
98
0
    if (trig->running) {
99
        /* Wait until the existing job is complete before starting the next one */
100
0
        return G_SOURCE_CONTINUE;
101
0
    }
102
0
    trig->trigger = false;
103
104
0
    if (callback) {
105
0
        int callback_rc = callback(trig->user_data);
106
107
0
        if (callback_rc < 0) {
108
0
            pcmk__trace("Trigger handler %p not yet complete", trig);
109
0
            trig->running = true;
110
0
        } else if (callback_rc == 0) {
111
0
            rc = G_SOURCE_REMOVE;
112
0
        }
113
0
    }
114
0
    return rc;
115
0
}
116
117
static void
118
crm_trigger_finalize(GSource * source)
119
0
{
120
0
    pcmk__trace("Trigger %p destroyed", source);
121
0
}
122
123
static GSourceFuncs crm_trigger_funcs = {
124
    crm_trigger_prepare,
125
    crm_trigger_check,
126
    crm_trigger_dispatch,
127
    crm_trigger_finalize,
128
};
129
130
static crm_trigger_t *
131
mainloop_setup_trigger(GSource * source, int priority,
132
                       int (*dispatch)(void *user_data), void *userdata)
133
0
{
134
0
    crm_trigger_t *trigger = NULL;
135
136
0
    trigger = (crm_trigger_t *) source;
137
138
0
    trigger->id = 0;
139
0
    trigger->trigger = false;
140
0
    trigger->user_data = userdata;
141
142
0
    if (dispatch) {
143
0
        g_source_set_callback(source, dispatch, trigger, NULL);
144
0
    }
145
146
0
    g_source_set_priority(source, priority);
147
0
    g_source_set_can_recurse(source, FALSE);
148
149
0
    trigger->id = g_source_attach(source, NULL);
150
0
    return trigger;
151
0
}
152
153
void
154
mainloop_trigger_complete(crm_trigger_t * trig)
155
0
{
156
0
    pcmk__trace("Trigger handler %p complete", trig);
157
0
    trig->running = false;
158
0
}
159
160
/*!
161
 * \brief Create a trigger to be used as a mainloop source
162
 *
163
 * \param[in] priority  Relative priority of source (lower number is higher priority)
164
 * \param[in] dispatch  Trigger dispatch function (should return 0 to remove the
165
 *                      trigger from the mainloop, -1 if the trigger should be
166
 *                      kept but the job is still running and not complete, and
167
 *                      1 if the trigger should be kept and the job is complete)
168
 * \param[in] userdata  Pointer to pass to \p dispatch
169
 *
170
 * \return Newly allocated mainloop source for trigger
171
 */
172
crm_trigger_t *
173
mainloop_add_trigger(int priority, int (*dispatch) (void *user_data),
174
                     void *userdata)
175
0
{
176
0
    GSource *source = NULL;
177
178
0
    pcmk__assert(sizeof(crm_trigger_t) > sizeof(GSource));
179
0
    source = g_source_new(&crm_trigger_funcs, sizeof(crm_trigger_t));
180
181
0
    return mainloop_setup_trigger(source, priority, dispatch, userdata);
182
0
}
183
184
void
185
mainloop_set_trigger(crm_trigger_t * source)
186
0
{
187
0
    if(source) {
188
0
        source->trigger = true;
189
0
    }
190
0
}
191
192
gboolean
193
mainloop_destroy_trigger(crm_trigger_t * source)
194
0
{
195
0
    GSource *gs = NULL;
196
197
0
    if(source == NULL) {
198
0
        return TRUE;
199
0
    }
200
201
0
    gs = (GSource *)source;
202
203
0
    g_source_destroy(gs); /* Remove from mainloop, ref_count-- */
204
0
    g_source_unref(gs); /* The caller no longer carries a reference to source
205
                         *
206
                         * At this point the source should be free'd,
207
                         * unless we're currently processing said
208
                         * source, in which case mainloop holds an
209
                         * additional reference and it will be free'd
210
                         * once our processing completes
211
                         */
212
0
    return TRUE;
213
0
}
214
215
// Define a custom glib source for signal handling
216
217
// Data structure for custom glib source
218
typedef struct {
219
    crm_trigger_t trigger;      // trigger that invoked source (must be first)
220
    void (*handler) (int sig);  // signal handler
221
    int signal;                 // signal that was received
222
} crm_signal_t;
223
224
// Table to associate signal handlers with signal numbers
225
static crm_signal_t *crm_signals[NSIG];
226
227
/*!
228
 * \internal
229
 * \brief Dispatch an event from custom glib source for signals
230
 *
231
 * Given an signal event, clear the event trigger and call any registered
232
 * signal handler.
233
 *
234
 * \param[in] source    glib source that triggered this dispatch
235
 * \param[in] callback  (ignored)
236
 * \param[in] userdata  (ignored)
237
 */
238
static gboolean
239
crm_signal_dispatch(GSource *source, GSourceFunc callback, void *userdata)
240
0
{
241
0
    crm_signal_t *sig = (crm_signal_t *) source;
242
243
0
    if(sig->signal != SIGCHLD) {
244
0
        pcmk__notice("Caught '%s' signal " QB_XS " %d (%s handler)",
245
0
                     strsignal(sig->signal), sig->signal,
246
0
                     ((sig->handler != NULL)? "invoking" : "no"));
247
0
    }
248
249
0
    sig->trigger.trigger = false;
250
0
    if (sig->handler) {
251
0
        sig->handler(sig->signal);
252
0
    }
253
0
    return TRUE;
254
0
}
255
256
/*!
257
 * \internal
258
 * \brief Handle a signal by setting a trigger for signal source
259
 *
260
 * \param[in] sig  Signal number that was received
261
 *
262
 * \note This is the true signal handler for the mainloop signal source, and
263
 *       must be async-safe.
264
 */
265
static void
266
mainloop_signal_handler(int sig)
267
0
{
268
0
    if (sig > 0 && sig < NSIG && crm_signals[sig] != NULL) {
269
0
        mainloop_set_trigger((crm_trigger_t *) crm_signals[sig]);
270
0
    }
271
0
}
272
273
// Functions implementing our custom glib source for signal handling
274
static GSourceFuncs crm_signal_funcs = {
275
    crm_trigger_prepare,
276
    crm_trigger_check,
277
    crm_signal_dispatch,
278
    crm_trigger_finalize,
279
};
280
281
/*!
282
 * \internal
283
 * \brief Set a true signal handler
284
 *
285
 * signal()-like interface to sigaction()
286
 *
287
 * \param[in] sig       Signal number to register handler for
288
 * \param[in] dispatch  Signal handler
289
 *
290
 * \return The previous value of the signal handler, or SIG_ERR on error
291
 * \note The dispatch function must be async-safe.
292
 */
293
sighandler_t
294
crm_signal_handler(int sig, sighandler_t dispatch)
295
0
{
296
0
    sigset_t mask;
297
0
    struct sigaction sa;
298
0
    struct sigaction old;
299
300
0
    if (sigemptyset(&mask) < 0) {
301
0
        pcmk__err("Could not %sset handler for signal %d: %s",
302
0
                  ((dispatch == NULL)? "un" : ""), sig, strerror(errno));
303
0
        return SIG_ERR;
304
0
    }
305
306
0
    memset(&sa, 0, sizeof(struct sigaction));
307
0
    sa.sa_handler = dispatch;
308
0
    sa.sa_flags = SA_RESTART;
309
0
    sa.sa_mask = mask;
310
311
0
    if (sigaction(sig, &sa, &old) < 0) {
312
0
        pcmk__err("Could not %sset handler for signal %d: %s",
313
0
                  ((dispatch == NULL)? "un" : ""), sig, strerror(errno));
314
0
        return SIG_ERR;
315
0
    }
316
0
    return old.sa_handler;
317
0
}
318
319
static void
320
mainloop_destroy_signal_entry(int sig)
321
0
{
322
0
    crm_signal_t *tmp = crm_signals[sig];
323
324
0
    if (tmp != NULL) {
325
0
        crm_signals[sig] = NULL;
326
0
        pcmk__trace("Unregistering mainloop handler for signal %d", sig);
327
0
        mainloop_destroy_trigger((crm_trigger_t *) tmp);
328
0
    }
329
0
}
330
331
/*!
332
 * \internal
333
 * \brief Add a signal handler to a mainloop
334
 *
335
 * \param[in] sig       Signal number to handle
336
 * \param[in] dispatch  Signal handler function (\c NULL to ignore the signal)
337
 *
338
 * \note The true signal handler merely sets a mainloop trigger to call this
339
 *       dispatch function via the mainloop. Therefore, the dispatch function
340
 *       does not need to be async-safe.
341
 * \note The added signal handler gets freed by \c mainloop_cleanup() if it is
342
 *       not freed manually using \c mainloop_destroy_signal().
343
 */
344
gboolean
345
mainloop_add_signal(int sig, void (*dispatch) (int sig))
346
0
{
347
0
    GSource *source = NULL;
348
0
    int priority = G_PRIORITY_HIGH - 1;
349
350
0
    if (sig == SIGTERM) {
351
        /* TERM is higher priority than other signals,
352
         *   signals are higher priority than other ipc.
353
         * Yes, minus: smaller is "higher"
354
         */
355
0
        priority--;
356
0
    }
357
358
0
    if (sig >= NSIG || sig < 0) {
359
0
        pcmk__err("Signal %d is out of range", sig);
360
0
        return FALSE;
361
362
0
    } else if (crm_signals[sig] != NULL && crm_signals[sig]->handler == dispatch) {
363
0
        pcmk__trace("Signal handler for %d is already installed", sig);
364
0
        return TRUE;
365
366
0
    } else if (crm_signals[sig] != NULL) {
367
0
        pcmk__err("Different signal handler for %d is already installed", sig);
368
0
        return FALSE;
369
0
    }
370
371
0
    pcmk__assert(sizeof(crm_signal_t) > sizeof(GSource));
372
0
    source = g_source_new(&crm_signal_funcs, sizeof(crm_signal_t));
373
374
0
    crm_signals[sig] = (crm_signal_t *) mainloop_setup_trigger(source, priority, NULL, NULL);
375
0
    pcmk__assert(crm_signals[sig] != NULL);
376
377
0
    crm_signals[sig]->handler = dispatch;
378
0
    crm_signals[sig]->signal = sig;
379
380
0
    if (crm_signal_handler(sig, mainloop_signal_handler) == SIG_ERR) {
381
0
        mainloop_destroy_signal_entry(sig);
382
0
        return FALSE;
383
0
    }
384
385
0
    return TRUE;
386
0
}
387
388
gboolean
389
mainloop_destroy_signal(int sig)
390
0
{
391
0
    if (sig >= NSIG || sig < 0) {
392
0
        pcmk__err("Signal %d is out of range", sig);
393
0
        return FALSE;
394
395
0
    } else if (crm_signal_handler(sig, NULL) == SIG_ERR) {
396
        // Error already logged
397
0
        return FALSE;
398
399
0
    } else if (crm_signals[sig] == NULL) {
400
0
        return TRUE;
401
0
    }
402
0
    mainloop_destroy_signal_entry(sig);
403
0
    return TRUE;
404
0
}
405
406
/*
407
 * libqb...
408
 */
409
struct gio_to_qb_poll {
410
    int32_t is_used;
411
    unsigned int source;
412
    int32_t events;
413
    void *data;
414
    qb_ipcs_dispatch_fn_t fn;
415
    enum qb_loop_priority p;
416
};
417
418
static gboolean
419
gio_read_socket(GIOChannel * gio, GIOCondition condition, void *data)
420
0
{
421
0
    struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
422
0
    int fd = g_io_channel_unix_get_fd(gio);
423
424
0
    pcmk__trace("%p.%d %d", data, fd, condition);
425
426
    /* if this assert get's hit, then there is a race condition between
427
     * when we destroy a fd and when mainloop actually gives it up */
428
0
    pcmk__assert(adaptor->is_used > 0);
429
430
0
    return (adaptor->fn(fd, condition, adaptor->data) == 0);
431
0
}
432
433
static void
434
gio_poll_destroy(void *data)
435
0
{
436
0
    struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
437
438
0
    adaptor->is_used--;
439
0
    pcmk__assert(adaptor->is_used >= 0);
440
441
0
    if (adaptor->is_used == 0) {
442
0
        pcmk__trace("Marking adaptor %p unused", adaptor);
443
0
        adaptor->source = 0;
444
0
    }
445
0
}
446
447
/*!
448
 * \internal
449
 * \brief Convert libqb's poll priority into GLib's one
450
 *
451
 * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
452
 *
453
 * \return  best matching GLib's priority
454
 */
455
static int
456
conv_prio_libqb2glib(enum qb_loop_priority prio)
457
0
{
458
0
    switch (prio) {
459
0
        case QB_LOOP_LOW:   return G_PRIORITY_LOW;
460
0
        case QB_LOOP_HIGH:  return G_PRIORITY_HIGH;
461
0
        default:            return G_PRIORITY_DEFAULT; // QB_LOOP_MED
462
0
    }
463
0
}
464
465
/*!
466
 * \internal
467
 * \brief Convert libqb's poll priority to rate limiting spec
468
 *
469
 * \param[in] prio  libqb's poll priority (#QB_LOOP_MED assumed as fallback)
470
 *
471
 * \return  best matching rate limiting spec
472
 * \note This is the inverse of libqb's qb_ipcs_request_rate_limit().
473
 */
474
static enum qb_ipcs_rate_limit
475
conv_libqb_prio2ratelimit(enum qb_loop_priority prio)
476
0
{
477
0
    switch (prio) {
478
0
        case QB_LOOP_LOW:   return QB_IPCS_RATE_SLOW;
479
0
        case QB_LOOP_HIGH:  return QB_IPCS_RATE_FAST;
480
0
        default:            return QB_IPCS_RATE_NORMAL; // QB_LOOP_MED
481
0
    }
482
0
}
483
484
static int32_t
485
gio_poll_dispatch_update(enum qb_loop_priority p, int32_t fd, int32_t evts,
486
                         void *data, qb_ipcs_dispatch_fn_t fn, int32_t add)
487
0
{
488
0
    struct gio_to_qb_poll *adaptor;
489
0
    GIOChannel *channel;
490
0
    int32_t res = 0;
491
492
0
    res = qb_array_index(gio_map, fd, (void **)&adaptor);
493
0
    if (res < 0) {
494
0
        pcmk__err("Array lookup failed for fd=%d: %d", fd, res);
495
0
        return res;
496
0
    }
497
498
0
    pcmk__trace("Adding fd=%d to mainloop as adaptor %p", fd, adaptor);
499
500
0
    if (add && adaptor->source) {
501
0
        pcmk__err("Adaptor for descriptor %d is still in-use", fd);
502
0
        return -EEXIST;
503
0
    }
504
0
    if (!add && !adaptor->is_used) {
505
0
        pcmk__err("Adaptor for descriptor %d is not in-use", fd);
506
0
        return -ENOENT;
507
0
    }
508
509
    /* channel is created with ref_count = 1 */
510
0
    channel = g_io_channel_unix_new(fd);
511
0
    if (!channel) {
512
0
        pcmk__err("No memory left to add fd=%d", fd);
513
0
        return -ENOMEM;
514
0
    }
515
516
0
    if (adaptor->source) {
517
0
        g_source_remove(adaptor->source);
518
0
        adaptor->source = 0;
519
0
    }
520
521
    /* Because unlike the poll() API, glib doesn't tell us about HUPs by default */
522
0
    evts |= (G_IO_HUP | G_IO_NVAL | G_IO_ERR);
523
524
0
    adaptor->fn = fn;
525
0
    adaptor->events = evts;
526
0
    adaptor->data = data;
527
0
    adaptor->p = p;
528
0
    adaptor->is_used++;
529
0
    adaptor->source =
530
0
        g_io_add_watch_full(channel, conv_prio_libqb2glib(p), evts,
531
0
                            gio_read_socket, adaptor, gio_poll_destroy);
532
533
    /* Now that mainloop now holds a reference to channel,
534
     * thanks to g_io_add_watch_full(), drop ours from g_io_channel_unix_new().
535
     *
536
     * This means that channel will be free'd by:
537
     * g_main_context_dispatch()
538
     *  -> g_source_destroy_internal()
539
     *      -> g_source_callback_unref()
540
     * shortly after gio_poll_destroy() completes
541
     */
542
0
    g_io_channel_unref(channel);
543
544
0
    pcmk__trace("Added to mainloop with gsource id=%d", adaptor->source);
545
0
    if (adaptor->source > 0) {
546
0
        return 0;
547
0
    }
548
549
0
    return -EINVAL;
550
0
}
551
552
static int32_t
553
gio_poll_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
554
                      void *data, qb_ipcs_dispatch_fn_t fn)
555
0
{
556
0
    return gio_poll_dispatch_update(p, fd, evts, data, fn, QB_TRUE);
557
0
}
558
559
static int32_t
560
gio_poll_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts,
561
                      void *data, qb_ipcs_dispatch_fn_t fn)
562
0
{
563
0
    return gio_poll_dispatch_update(p, fd, evts, data, fn, QB_FALSE);
564
0
}
565
566
static int32_t
567
gio_poll_dispatch_del(int32_t fd)
568
0
{
569
0
    struct gio_to_qb_poll *adaptor;
570
571
0
    pcmk__trace("Looking for fd=%d", fd);
572
0
    if (qb_array_index(gio_map, fd, (void **)&adaptor) == 0) {
573
0
        if (adaptor->source) {
574
0
            g_source_remove(adaptor->source);
575
0
            adaptor->source = 0;
576
0
        }
577
0
    }
578
0
    return 0;
579
0
}
580
581
struct qb_ipcs_poll_handlers gio_poll_funcs = {
582
    .job_add = NULL,
583
    .dispatch_add = gio_poll_dispatch_add,
584
    .dispatch_mod = gio_poll_dispatch_mod,
585
    .dispatch_del = gio_poll_dispatch_del,
586
};
587
588
qb_ipcs_service_t *
589
mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
590
                        struct qb_ipcs_service_handlers *callbacks)
591
0
{
592
0
    return mainloop_add_ipc_server_with_prio(name, type, callbacks, QB_LOOP_MED);
593
0
}
594
595
qb_ipcs_service_t *
596
mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type,
597
                                  struct qb_ipcs_service_handlers *callbacks,
598
                                  enum qb_loop_priority prio)
599
0
{
600
0
    int rc = 0;
601
0
    qb_ipcs_service_t *server = NULL;
602
603
0
    if (gio_map == NULL) {
604
0
        gio_map = qb_array_create_2(64, sizeof(struct gio_to_qb_poll), 1);
605
0
    }
606
607
0
    server = qb_ipcs_create(name, 0, QB_IPC_SHM, callbacks);
608
609
0
    if (server == NULL) {
610
0
        pcmk__err("Could not create %s IPC server: %s (%d)", name,
611
0
                  pcmk_rc_str(errno), errno);
612
0
        return NULL;
613
0
    }
614
615
0
    if (prio != QB_LOOP_MED) {
616
0
        qb_ipcs_request_rate_limit(server, conv_libqb_prio2ratelimit(prio));
617
0
    }
618
619
    // Enforce a minimum IPC buffer size on all clients
620
0
    qb_ipcs_enforce_buffer_size(server, crm_ipc_default_buffer_size());
621
0
    qb_ipcs_poll_handlers_set(server, &gio_poll_funcs);
622
623
0
    rc = qb_ipcs_run(server);
624
0
    if (rc < 0) {
625
0
        pcmk__err("Could not start %s IPC server: %s (%d)", name,
626
0
                  pcmk_strerror(rc), rc);
627
0
        return NULL; // qb_ipcs_run() destroys server on failure
628
0
    }
629
630
0
    return server;
631
0
}
632
633
void
634
mainloop_del_ipc_server(qb_ipcs_service_t * server)
635
0
{
636
0
    if (server) {
637
0
        qb_ipcs_destroy(server);
638
0
    }
639
0
}
640
641
/*!
642
 * \internal
643
 * \brief I/O watch callback function (GIOFunc)
644
 *
645
 * \param[in] gio        I/O channel being watched
646
 * \param[in] condition  I/O condition satisfied
647
 * \param[in] data       User data passed when source was created
648
 *
649
 * \return G_SOURCE_REMOVE to remove source, G_SOURCE_CONTINUE to keep it
650
 */
651
static gboolean
652
mainloop_gio_callback(GIOChannel *gio, GIOCondition condition, void *data)
653
0
{
654
0
    gboolean rc = G_SOURCE_CONTINUE;
655
0
    mainloop_io_t *client = data;
656
657
0
    pcmk__assert(client->fd == g_io_channel_unix_get_fd(gio));
658
659
0
    if (condition & G_IO_IN) {
660
0
        if (client->ipc) {
661
0
            long read_rc = 0L;
662
0
            int max = 10;
663
664
0
            do {
665
0
                read_rc = crm_ipc_read(client->ipc);
666
0
                if (read_rc <= 0) {
667
0
                    pcmk__trace("Could not read IPC message from %s: %s (%ld)",
668
0
                                client->name, pcmk_strerror(read_rc), read_rc);
669
670
0
                    if (read_rc == -EAGAIN) {
671
0
                        continue;
672
0
                    }
673
674
0
                } else if (client->dispatch_fn_ipc) {
675
0
                    const char *buffer = crm_ipc_buffer(client->ipc);
676
677
0
                    pcmk__trace("New %ld-byte IPC message from %s after I/O "
678
0
                                "condition %d",
679
0
                                read_rc, client->name, (int) condition);
680
0
                    if (client->dispatch_fn_ipc(buffer, read_rc, client->userdata) < 0) {
681
0
                        pcmk__trace("Connection to %s no longer required",
682
0
                                    client->name);
683
0
                        rc = G_SOURCE_REMOVE;
684
0
                    }
685
0
                }
686
687
0
                pcmk__ipc_free_client_buffer(client->ipc);
688
689
0
            } while ((rc == G_SOURCE_CONTINUE) && (--max > 0)
690
0
                      && ((read_rc > 0) || (read_rc == -EAGAIN)));
691
692
0
        } else {
693
0
            pcmk__trace("New I/O event for %s after I/O condition %d",
694
0
                        client->name, (int) condition);
695
0
            if (client->dispatch_fn_io) {
696
0
                if (client->dispatch_fn_io(client->userdata) < 0) {
697
0
                    pcmk__trace("Connection to %s no longer required",
698
0
                                client->name);
699
0
                    rc = G_SOURCE_REMOVE;
700
0
                }
701
0
            }
702
0
        }
703
0
    }
704
705
0
    if (client->ipc && !crm_ipc_connected(client->ipc)) {
706
0
        pcmk__err("Connection to %s closed " QB_XS " client=%p condition=%d",
707
0
                  client->name, client, condition);
708
0
        rc = G_SOURCE_REMOVE;
709
710
0
    } else if (condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR)) {
711
0
        pcmk__trace("The connection %s[%p] has been closed (I/O condition=%d)",
712
0
                    client->name, client, condition);
713
0
        rc = G_SOURCE_REMOVE;
714
715
0
    } else if ((condition & G_IO_IN) == 0) {
716
        /*
717
           #define      GLIB_SYSDEF_POLLIN     =1
718
           #define      GLIB_SYSDEF_POLLPRI    =2
719
           #define      GLIB_SYSDEF_POLLOUT    =4
720
           #define      GLIB_SYSDEF_POLLERR    =8
721
           #define      GLIB_SYSDEF_POLLHUP    =16
722
           #define      GLIB_SYSDEF_POLLNVAL   =32
723
724
           typedef enum
725
           {
726
           G_IO_IN      GLIB_SYSDEF_POLLIN,
727
           G_IO_OUT     GLIB_SYSDEF_POLLOUT,
728
           G_IO_PRI     GLIB_SYSDEF_POLLPRI,
729
           G_IO_ERR     GLIB_SYSDEF_POLLERR,
730
           G_IO_HUP     GLIB_SYSDEF_POLLHUP,
731
           G_IO_NVAL    GLIB_SYSDEF_POLLNVAL
732
           } GIOCondition;
733
734
           A bitwise combination representing a condition to watch for on an event source.
735
736
           G_IO_IN      There is data to read.
737
           G_IO_OUT     Data can be written (without blocking).
738
           G_IO_PRI     There is urgent data to read.
739
           G_IO_ERR     Error condition.
740
           G_IO_HUP     Hung up (the connection has been broken, usually for pipes and sockets).
741
           G_IO_NVAL    Invalid request. The file descriptor is not open.
742
         */
743
0
        pcmk__err("Strange condition: %d", condition);
744
0
    }
745
746
    /* G_SOURCE_REMOVE results in mainloop_gio_destroy() being called
747
     * just before the source is removed from mainloop
748
     */
749
0
    return rc;
750
0
}
751
752
static void
753
mainloop_gio_destroy(void *c)
754
0
{
755
0
    mainloop_io_t *client = c;
756
757
    /* client->source is valid but about to be destroyed (ref_count == 0) in
758
     * gmain.c. client->channel will still have ref_count > 0 (should be == 1).
759
     */
760
0
    pcmk__trace("Destroying client %s[%p]", client->name, client);
761
762
    // @TODO Would it be safe to call this immediately before crm_ipc_destroy()?
763
0
    crm_ipc_close(client->ipc);
764
765
0
    if (client->destroy_fn != NULL) {
766
0
        client->destroy_fn(client->userdata);
767
0
    }
768
769
0
    crm_ipc_destroy(client->ipc);
770
771
0
    pcmk__trace("Destroyed client %s[%p]", client->name, client);
772
773
    /* This is the destructor corresponding to mainloop_add_fd(). There,
774
     * g_io_channel_unix_new() created client->channel and added a reference to
775
     * it, so we drop a reference here. The channel will be freed when the
776
     * reference count drops to zero.
777
     */
778
0
    g_io_channel_unref(client->channel);
779
780
0
    free(client->name);
781
0
    free(client);
782
0
}
783
784
/*!
785
 * \brief Connect to IPC and add it as a main loop source
786
 *
787
 * \param[in,out] ipc        IPC connection to add
788
 * \param[in]     priority   Event source priority to use for connection
789
 * \param[in]     userdata   Data to register with callbacks
790
 * \param[in]     callbacks  Dispatch and destroy callbacks for connection
791
 * \param[out]    source     Newly allocated event source
792
 *
793
 * \return Standard Pacemaker return code
794
 *
795
 * \note On failure, the caller is still responsible for ipc. On success, the
796
 *       caller should call mainloop_del_ipc_client() when source is no longer
797
 *       needed, which will lead to the disconnection of the IPC later in the
798
 *       main loop if it is connected. However the IPC disconnects,
799
 *       mainloop_gio_destroy() will free ipc and source after calling the
800
 *       destroy callback.
801
 */
802
int
803
pcmk__add_mainloop_ipc(crm_ipc_t *ipc, int priority, void *userdata,
804
                       const struct ipc_client_callbacks *callbacks,
805
                       mainloop_io_t **source)
806
0
{
807
0
    int rc = pcmk_rc_ok;
808
0
    int fd = -1;
809
0
    const char *ipc_name = NULL;
810
811
0
    CRM_CHECK((ipc != NULL) && (callbacks != NULL), return EINVAL);
812
813
0
    ipc_name = pcmk__s(crm_ipc_name(ipc), "Pacemaker");
814
0
    rc = pcmk__connect_generic_ipc(ipc);
815
0
    if (rc != pcmk_rc_ok) {
816
0
        pcmk__debug("Connection to %s failed: %s", ipc_name, pcmk_rc_str(rc));
817
0
        return rc;
818
0
    }
819
820
0
    rc = pcmk__ipc_fd(ipc, &fd);
821
0
    if (rc != pcmk_rc_ok) {
822
0
        pcmk__debug("Could not obtain file descriptor for %s IPC: %s", ipc_name,
823
0
                    pcmk_rc_str(rc));
824
0
        crm_ipc_close(ipc);
825
0
        return rc;
826
0
    }
827
828
0
    *source = mainloop_add_fd(ipc_name, priority, fd, userdata, NULL);
829
0
    if (*source == NULL) {
830
0
        rc = errno;
831
0
        crm_ipc_close(ipc);
832
0
        return rc;
833
0
    }
834
835
0
    (*source)->ipc = ipc;
836
0
    (*source)->destroy_fn = callbacks->destroy;
837
0
    (*source)->dispatch_fn_ipc = callbacks->dispatch;
838
0
    return pcmk_rc_ok;
839
0
}
840
841
mainloop_io_t *
842
mainloop_add_ipc_client(const char *name, int priority, size_t max_size,
843
                        void *userdata, struct ipc_client_callbacks *callbacks)
844
0
{
845
0
    crm_ipc_t *ipc = crm_ipc_new(name, 0);
846
0
    mainloop_io_t *source = NULL;
847
0
    int rc = pcmk__add_mainloop_ipc(ipc, priority, userdata, callbacks,
848
0
                                    &source);
849
850
0
    if (rc != pcmk_rc_ok) {
851
0
        if (crm_log_level == PCMK__LOG_STDOUT) {
852
0
            fprintf(stderr, "Connection to %s failed: %s",
853
0
                    name, pcmk_rc_str(rc));
854
0
        }
855
0
        crm_ipc_destroy(ipc);
856
0
        if (rc > 0) {
857
0
            errno = rc;
858
0
        } else {
859
0
            errno = ENOTCONN;
860
0
        }
861
0
        return NULL;
862
0
    }
863
0
    return source;
864
0
}
865
866
void
867
mainloop_del_ipc_client(mainloop_io_t * client)
868
0
{
869
0
    mainloop_del_fd(client);
870
0
}
871
872
crm_ipc_t *
873
mainloop_get_ipc_client(mainloop_io_t * client)
874
0
{
875
0
    if (client) {
876
0
        return client->ipc;
877
0
    }
878
0
    return NULL;
879
0
}
880
881
mainloop_io_t *
882
mainloop_add_fd(const char *name, int priority, int fd, void *userdata,
883
                struct mainloop_fd_callbacks * callbacks)
884
0
{
885
0
    mainloop_io_t *client = NULL;
886
0
    const GIOCondition condition = G_IO_IN|G_IO_HUP|G_IO_NVAL|G_IO_ERR;
887
888
0
    if (fd < 0) {
889
0
        errno = EINVAL;
890
0
        return NULL;
891
0
    }
892
893
0
    client = pcmk__assert_alloc(1, sizeof(mainloop_io_t));
894
0
    client->name = pcmk__str_copy(name);
895
0
    client->userdata = userdata;
896
897
0
    if (callbacks != NULL) {
898
0
        client->destroy_fn = callbacks->destroy;
899
0
        client->dispatch_fn_io = callbacks->dispatch;
900
0
    }
901
902
0
    client->fd = fd;
903
0
    client->channel = g_io_channel_unix_new(fd);
904
0
    client->source = g_io_add_watch_full(client->channel, priority, condition,
905
0
                                         mainloop_gio_callback, client,
906
0
                                         mainloop_gio_destroy);
907
908
0
    pcmk__trace("Added connection %d for %s[%p].%d", client->source,
909
0
                client->name, client, fd);
910
0
    return client;
911
0
}
912
913
void
914
mainloop_del_fd(mainloop_io_t *client)
915
0
{
916
0
    if ((client == NULL) || (client->source == 0)) {
917
0
        return;
918
0
    }
919
920
0
    pcmk__trace("Removing client %s[%p]", client->name, client);
921
922
    /* g_source_remove() marks the source as destroyed, unsets the source
923
     * callback (mainloop_gio_callback()), and destroys the callback data (the
924
     * client) via the notify function (mainloop_gio_destroy()). We can rely on
925
     * mainloop_gio_callback() not getting called again for this source, and on
926
     * the client being destroyed.
927
     */
928
0
    g_source_remove(client->source);
929
0
}
930
931
/*!
932
 * \internal
933
 * \brief Send \c SIGKILL to a main loop child process or its process group
934
 *
935
 * If \p child->kill_group is set, kill the child's entire process group.
936
 * Otherwise, kill only the child process itself.
937
 *
938
 * \param[in] child  Main loop child
939
 *
940
 * \return Standard Pacemaker return code (\c pcmk_rc_ok if \c kill() returns 0,
941
 *         or \c errno after calling \c kill() otherwise)
942
 */
943
static int
944
kill_child_pid(const pcmk__main_loop_child_t *child)
945
0
{
946
0
    const pid_t pid = (child->kill_group? -child->pid : child->pid);
947
0
    int rc = 0;
948
949
0
    pcmk__debug("Killing PID %lld", (long long) pid);
950
951
0
    rc = kill(pid, SIGKILL);
952
0
    if (rc == 0) {
953
0
        return pcmk_rc_ok;
954
0
    }
955
956
0
    rc = errno;
957
0
    if (rc == ESRCH) {
958
0
        return rc;
959
0
    }
960
961
0
    pcmk__err("kill(%lld, KILL) failed for child '%s': %s", (long long) pid,
962
0
              pcmk__s(child->desc, ""), strerror(rc));
963
0
    return rc;
964
0
}
965
966
/*!
967
 * \internal
968
 * \brief Kill a child process after its timeout has expired
969
 *
970
 * \param[in,out] user_data  Main loop child
971
 *                           (<tt>pcmk__main_loop_child_t *</tt>)
972
 *
973
 * \return \c G_SOURCE_REMOVE (to destroy the timeout that triggered this call)
974
 *
975
 * \note This is a \c GSourceFunc.
976
 */
977
static gboolean
978
child_timeout_callback(void *user_data)
979
0
{
980
0
    pcmk__main_loop_child_t *child = user_data;
981
0
    int rc = pcmk_rc_ok;
982
0
    const char *result_s = NULL;
983
984
0
    child->timer_id = 0;
985
0
    child->timed_out = true;
986
987
0
    rc = kill_child_pid(child);
988
989
0
    switch (rc) {
990
0
        case pcmk_rc_ok:
991
0
            result_s = "was successfully killed";
992
0
            break;
993
994
0
        case ESRCH:
995
0
            result_s = "has already terminated";
996
0
            break;
997
998
0
        default:
999
0
            result_s = "could not be killed";
1000
0
            break;
1001
0
    }
1002
1003
0
    pcmk__debug("%s process (PID %lld) timed out and %s", child->desc,
1004
0
                (long long) child->pid, result_s);
1005
0
    return G_SOURCE_REMOVE;
1006
0
}
1007
1008
/*!
1009
 * \internal
1010
 * \brief Free a main loop child
1011
 *
1012
 * If the child has an associated timer, remove it.
1013
 *
1014
 * \param[in,out] data  Main loop child (<tt>pcmk__main_loop_child_t *</tt>)
1015
 *
1016
 * \note This does not free the child's \c user_data field.
1017
 * \note This is a \c GDestroyNotify.
1018
 */
1019
static void
1020
free_main_loop_child(void *data)
1021
0
{
1022
0
    pcmk__main_loop_child_t *child = data;
1023
1024
0
    if (child == NULL) {
1025
0
        return;
1026
0
    }
1027
1028
0
    if (child->timer_id != 0) {
1029
0
        pcmk__trace("Removing timer %u", child->timer_id);
1030
0
        g_source_remove(child->timer_id);
1031
0
    }
1032
1033
0
    free(child->desc);
1034
0
    free(child);
1035
0
}
1036
1037
/*!
1038
 * \internal
1039
 * \brief Wait on a child process and free it if terminated
1040
 *
1041
 * If the child has terminated, call its exit callback if any, remove it from
1042
 * \c child_list, and free it.
1043
 *
1044
 * Likely bug: If the child object's \c pid field is nonpositive, then we wait
1045
 * on the corresponding process group as documented in the \c wait(2) man page.
1046
 * On success, call the exit callback using that PID (not the PID of the actual
1047
 * child process that changed state). Also remove the child object from
1048
 * \c child_list and free the child object, even though there may still be other
1049
 * child processes in the same process group that have not yet been waited on.
1050
 * This seems incorrect. However, nothing internal creates a child object with
1051
 * nonpositive PID, and the \c mainloop_child_add() documentation notes that
1052
 * nonpositive PIDs are not expected to work correctly.
1053
 *
1054
 * \param[in,out] link     List element whose data is the child to wait for
1055
 * \param[in]     no_hang  If \c true, use the \c waitpid() \c WNOHANG option
1056
 *
1057
 * \return \c true if the child process (or a child process in the specified
1058
 *         process group) has terminated, or \c false if the child process is
1059
 *         still active or its state changed in an unexpected way
1060
 *
1061
 * \note Taking the list link rather than the child as an argument allows us to
1062
 *       delete a terminated child from \c child_list in constant time. If we
1063
 *       took the child, \c g_list_remove() would have to find the child in the
1064
 *       list again before removing it.
1065
 */
1066
static bool
1067
child_waitpid(GList *link, bool no_hang)
1068
0
{
1069
0
    const int options = no_hang? WNOHANG : 0;
1070
1071
0
    pcmk__main_loop_child_t *child = NULL;
1072
0
    pid_t rc = 0;
1073
0
    int status = 0;
1074
1075
0
    int core = 0;
1076
0
    int signo = 0;
1077
0
    int exit_code = 0;
1078
1079
0
    pcmk__assert(link != NULL);
1080
0
    child = link->data;
1081
1082
0
    rc = waitpid(child->pid, &status, options);
1083
1084
0
    if (rc == 0) {
1085
        // WNOHANG was specified and child->pid exists and has not changed state
1086
0
        pcmk__trace("Child process %lld (%s) still active",
1087
0
                    (long long) child->pid, child->desc);
1088
0
        return false;
1089
0
    }
1090
1091
0
    if (rc == -1) {
1092
0
        if (errno == ECHILD) {
1093
            /* This situation should probably never happen in practice. Setting
1094
             * exit_code to 1 is misleading in that it indicates the child
1095
             * exited with code 1, and we don't know that to be true. We could
1096
             * add a pcmk__main_loop_child_t flag to indicate this case, but it
1097
             * doesn't seem worth it.
1098
             */
1099
0
            exit_code = 1;
1100
1101
0
            pcmk__err("Wait for child process %lld (%s) failed because process "
1102
0
                      "does not exist or is not our child",
1103
0
                      (long long) child->pid, child->desc);
1104
0
            goto terminated;
1105
0
        }
1106
1107
0
        if (errno == EINTR) {
1108
0
            pcmk__notice("Wait for child process %lld (%s) was interrupted by "
1109
0
                         "a signal", (long long) child->pid, child->desc);
1110
0
            return false;
1111
0
        }
1112
1113
0
        pcmk__err("Bug: Wait for child process %lld (%s) failed: %s (waitpid() "
1114
0
                  "options: %#x)", (long long) child->pid, child->desc,
1115
0
                  strerror(errno), options);
1116
0
        return false;
1117
0
    }
1118
1119
    /* At this point, rc is the PID of a child whose state changed. If
1120
     * child->pid is positive, then rc == child->pid. Otherwise, rc is the PID
1121
     * of one of the child processes in the process group with ID -child->pid.
1122
     */
1123
1124
0
    if (rc != child->pid) {
1125
        /* @COMPAT Nothing internal creates a nonpositive child->pid, and the
1126
         * public Doxygen for mainloop_child_add() now notes that nonpositive
1127
         * PIDs are not expected to work correctly.
1128
         */
1129
0
        pcmk__trace("Child process %lld from group %lld (%s) terminated",
1130
0
                    (long long) rc, (long long) -child->pid, child->desc);
1131
0
        goto terminated;
1132
0
    }
1133
1134
0
    if (WIFEXITED(status)) {
1135
0
        exit_code = WEXITSTATUS(status);
1136
0
        pcmk__trace("Child process %lld (%s) exited with status %d",
1137
0
                    (long long) child->pid, child->desc, exit_code);
1138
0
        goto terminated;
1139
0
    }
1140
1141
0
    if (WIFSIGNALED(status)) {
1142
0
        signo = WTERMSIG(status);
1143
0
        pcmk__trace("Child process %lld (%s) was terminated by signal %d (%s)",
1144
0
                    (long long) child->pid, child->desc, signo,
1145
0
                    strsignal(signo));
1146
1147
0
#ifdef WCOREDUMP
1148
0
        if (WCOREDUMP(status)) {
1149
0
            core = 1;
1150
0
            pcmk__err("Child process %lld (%s) dumped core",
1151
0
                      (long long) child->pid, child->desc);
1152
0
        }
1153
0
#endif  // defined(WCOREDUMP)
1154
1155
0
        goto terminated;
1156
0
    }
1157
1158
    /* We're not using the WUNTRACED or WCONTINUED options. If the process
1159
     * changed state, it should have either exited or been terminated by a
1160
     * signal.
1161
     */
1162
0
    CRM_CHECK(false, return false);
1163
1164
0
terminated:
1165
0
    if (child->callback != NULL) {
1166
0
        child->callback(child, core, signo, exit_code);
1167
0
    }
1168
1169
0
    pcmk__trace("Removing terminated process %lld from child list",
1170
0
                (long long) child->pid);
1171
0
    child_list = g_list_delete_link(child_list, link);
1172
0
    free_main_loop_child(child);
1173
1174
0
    return true;
1175
0
}
1176
1177
/*!
1178
 * \internal
1179
 * \brief Free all main loop children whose processes have terminated
1180
 *
1181
 * If a child object's process has terminated, remove the child from
1182
 * \c child_list and free it.
1183
 *
1184
 * \param[in] signal  Ignored
1185
 */
1186
static void
1187
free_terminated_children(int signal)
1188
0
{
1189
0
    GList *iter = child_list;
1190
1191
0
    while (iter != NULL) {
1192
0
        GList *next = iter->next;
1193
1194
0
        child_waitpid(iter, true);
1195
0
        iter = next;
1196
0
    }
1197
0
}
1198
1199
/*!
1200
 * \internal
1201
 * \brief Install the main loop \c SIGCHLD handler
1202
 *
1203
 * Install \c free_terminated_children() as the \c SIGCHLD handler, and call it
1204
 * for any children that terminated before the handler was installed.
1205
 *
1206
 * \param[in] user_data  Ignored
1207
 *
1208
 * \return \c G_SOURCE_REMOVE (to destroy the timeout that triggered this call)
1209
 *
1210
 * \note This is a \c GSourceFunc.
1211
 */
1212
static gboolean
1213
install_sigchld_handler(void *user_data)
1214
0
{
1215
0
    pcmk__trace("Installing SIGCHLD handler");
1216
1217
    // Do NOT use g_child_watch_add() and friends, since they rely on pthreads
1218
0
    mainloop_add_signal(SIGCHLD, free_terminated_children);
1219
1220
0
    free_terminated_children(SIGCHLD);
1221
0
    return G_SOURCE_REMOVE;
1222
0
}
1223
1224
/*!
1225
 * \internal
1226
 * \brief Create a \c pcmk__main_loop_child_t object and add it to the main loop
1227
 *
1228
 * If the child process has not exited within \p timeout_ms, send it a
1229
 * \c SIGKILL signal.
1230
 *
1231
 * \param[in] pid         Child PID
1232
 * \param[in] desc        Description
1233
 * \param[in] timeout_ms  Timeout in milliseconds
1234
 * \param[in] user_data   User data
1235
 * \param[in] kill group  If \c true, kill the child's entire process group on
1236
 *                        timeout; otherwise, kill only the child process
1237
 * \param[in] callback    Function to call when the child process terminates
1238
 */
1239
void
1240
pcmk__main_loop_child_create(pid_t pid, const char *desc,
1241
                             unsigned int timeout_ms, void *user_data,
1242
                             bool kill_group,
1243
                             pcmk__main_loop_child_cb_t callback)
1244
0
{
1245
0
    static bool need_init = true;
1246
1247
0
    pcmk__main_loop_child_t *child = NULL;
1248
1249
0
    pcmk__assert(pid > 0);
1250
1251
0
    child = pcmk__assert_alloc(1, sizeof(pcmk__main_loop_child_t));
1252
0
    child->pid = pid;
1253
0
    child->desc = pcmk__str_copy(desc);
1254
0
    child->user_data = user_data;
1255
0
    child->kill_group = kill_group;
1256
0
    child->callback = callback;
1257
1258
0
    if (timeout_ms > 0) {
1259
0
        child->timer_id = pcmk__create_timer(timeout_ms, child_timeout_callback,
1260
0
                                             child);
1261
0
    }
1262
1263
0
    child_list = g_list_append(child_list, child);
1264
1265
0
    if (need_init) {
1266
        /* Invoke SIGCHLD processing from the main loop. This ensures that we
1267
         * don't add a child to the main loop and have the exit callback invoked
1268
         * for the child PID within the same call stack.
1269
         *
1270
         * @TODO Understand and document why this matters.
1271
         */
1272
0
        need_init = false;
1273
0
        pcmk__create_timer(1, install_sigchld_handler, NULL);
1274
0
    }
1275
0
}
1276
1277
/*!
1278
 * \internal
1279
 * \brief Compare two mainloop child objects by PID
1280
 *
1281
 * \param[in] a  First child to compare
1282
 *               (<tt>const pcmk__main_loop_child_t *</tt>)
1283
 * \param[in] b  Second child to compare
1284
 *               (<tt>const pcmk__main_loop_child_t *</tt>)
1285
 *
1286
 * \retval -1  if \p a->pid is less than \p b->pid
1287
 * \retval  0  if \p a->pid is equal to \p b->pid
1288
 * \retval  1  if \p a->pid is greater than \p b->pid
1289
 *
1290
 * \note This is a \c GCompareFunc.
1291
 */
1292
static int
1293
compare_children_by_pid(const void *a, const void *b)
1294
0
{
1295
0
    const pcmk__main_loop_child_t *child1 = a;
1296
0
    const pcmk__main_loop_child_t *child2 = b;
1297
1298
0
    if (child1->pid < child2->pid) {
1299
0
        return -1;
1300
0
    }
1301
1302
0
    if (child1->pid > child2->pid) {
1303
0
        return 1;
1304
0
    }
1305
1306
0
    return 0;
1307
0
}
1308
1309
/*!
1310
 * \internal
1311
 * \brief Kill a child process tracked by the main loop
1312
 *
1313
 * If a process with PID \p pid is being tracked, send it a \c SIGKILL.
1314
 *
1315
 * If this function kills the child process successfully, remove the child from
1316
 * the tracking data structure and free the child.
1317
 *
1318
 * If the process is being tracked but no longer exists, don't remove or free
1319
 * the child yet. We will do this later when we receive a \c SIGCHLD for the
1320
 * child process.
1321
 *
1322
 * \param[in] pid  Child PID
1323
 *
1324
 * \return \c true if the child with ID \p pid was being tracked and either this
1325
 *         function killed the process successfully or the process has already
1326
 *         terminated but we have not received a \c SIGCHLD for it; or \c false
1327
 *         otherwise
1328
 */
1329
bool
1330
pcmk__main_loop_child_kill(pid_t pid)
1331
0
{
1332
0
    const pcmk__main_loop_child_t cmp_data = { .pid = pid };
1333
0
    GList *match = NULL;
1334
0
    pcmk__main_loop_child_t *child = NULL;
1335
0
    int rc = pcmk_rc_ok;
1336
0
    bool no_hang = false;
1337
1338
0
    pcmk__assert(pid > 0);
1339
1340
0
    match = g_list_find_custom(child_list, &cmp_data, compare_children_by_pid);
1341
0
    if (match == NULL) {
1342
0
        return false;
1343
0
    }
1344
1345
0
    child = match->data;
1346
1347
0
    rc = kill_child_pid(child);
1348
0
    if (rc == ESRCH) {
1349
        /* It's gone but hasn't shown up in waitpid() yet. Wait until we get
1350
         * SIGCHLD and let handler clean it up as normal (so we get the correct
1351
         * return code/status). The blocking alternative would be to call
1352
         * child_waitpid(iter, false).
1353
         */
1354
0
        pcmk__trace("Waiting for signal that child process %lld completed",
1355
0
                    (long long) child->pid);
1356
0
        return true;
1357
0
    }
1358
1359
0
    if (rc != pcmk_rc_ok) {
1360
        /* If kill() failed for some other reason, set the WNOHANG flag, since
1361
         * we can't be certain what happened.
1362
         *
1363
         * If kill() succeeded, we don't need the WNOHANG flag because SIGKILL
1364
         * can't be blocked.
1365
         */
1366
0
        no_hang = true;
1367
0
    }
1368
1369
0
    return child_waitpid(match, no_hang);
1370
0
}
1371
1372
/*!
1373
 * \internal
1374
 * \brief Create a main loop timer
1375
 *
1376
 * \param[in] name         Timer name prefix (for logging only)
1377
 * \param[in] interval_ms  Timer interval
1378
 * \param[in] callback     Function to call after \p interval_ms expires
1379
 * \param[in] user_data    User data for \p callback
1380
 *
1381
 * \return Newly allocated main loop timer (guaranteed not to be \c NULL)
1382
 *
1383
 * \note The new timer's \c name string starts with the \p name argument and
1384
 *       includes the timer's interval and address.
1385
 * \note The caller is responsible for freeing the return value using
1386
 *       \c pcmk__main_loop_timer_free().
1387
 */
1388
pcmk__main_loop_timer_t *
1389
pcmk__main_loop_timer_new(const char *name, unsigned int interval_ms,
1390
                          GSourceFunc callback, void *user_data)
1391
0
{
1392
0
    pcmk__main_loop_timer_t *timer = NULL;
1393
0
    pcmk__assert((name != NULL) && (callback != NULL));
1394
1395
0
    timer = pcmk__assert_alloc(1, sizeof(pcmk__main_loop_timer_t));
1396
0
    timer->name = pcmk__assert_asprintf("%s-%u-%p", name, interval_ms, timer);
1397
0
    timer->interval_ms = interval_ms;
1398
0
    timer->cb = callback;
1399
0
    timer->user_data = user_data;
1400
1401
0
    pcmk__trace("Created timer %s with data %p", timer->name, user_data);
1402
0
    return timer;
1403
0
}
1404
1405
/*!
1406
 * \internal
1407
 * \brief Check whether a main loop timer is running
1408
 *
1409
 * A timer is running if its \c id field is nonzero, meaning that it has an
1410
 * active \c GSource with that ID associated with it.
1411
 *
1412
 * \param[in] timer  Main loop timer
1413
 *
1414
 * \return \c true if the timer is running, or \c false otherwise
1415
 */
1416
bool
1417
pcmk__main_loop_timer_running(const pcmk__main_loop_timer_t *timer)
1418
0
{
1419
0
    CRM_CHECK(timer != NULL, return false);
1420
1421
0
    return (timer->source_id != 0);
1422
0
}
1423
1424
/*!
1425
 * \internal
1426
 * \brief Stop a main loop timer
1427
 *
1428
 * Stopping a timer consists of removing its \c GSource and setting its \c id
1429
 * field to 0 (to indicate that it has no associated \c GSource).
1430
 *
1431
 * \param[in,out] timer  Main loop timer
1432
 */
1433
void
1434
pcmk__main_loop_timer_stop(pcmk__main_loop_timer_t *timer)
1435
0
{
1436
0
    CRM_CHECK(timer != NULL, return);
1437
1438
0
    if (!pcmk__main_loop_timer_running(timer)) {
1439
0
        return;
1440
0
    }
1441
1442
0
    pcmk__trace("Stopping timer %s", timer->name);
1443
0
    g_source_remove(timer->source_id);
1444
0
    timer->source_id = 0;
1445
0
}
1446
1447
/*!
1448
 * \internal
1449
 * \brief Run a main loop timer's callback
1450
 *
1451
 * If the callback returns \c G_SOURCE_REMOVE, set \p timer->source_id to 0 to
1452
 * indicate that the timer has no associated \c GSource.
1453
 *
1454
 * \param[in,out] user_data  Main loop timer
1455
 *                           (<tt>pcmk__main_loop_timer_t *</tt>)
1456
 *
1457
 * \return The return value from \p timer->cb (\c G_SOURCE_CONTINUE to keep the
1458
 *         timeout source, or \c G_SOURCE_REMOVE to remove it)
1459
 *
1460
 * \note This is a \c GSourceFunc.
1461
 */
1462
static gboolean
1463
main_loop_timer_cb(void *user_data)
1464
0
{
1465
0
    int id = 0;
1466
0
    pcmk__main_loop_timer_t *timer = user_data;
1467
1468
0
    pcmk__assert((timer != NULL) && (timer->cb != NULL));
1469
1470
    /* Ensure id is unset during callbacks so that
1471
     * pcmk__main_loop_timer_running() works as expected.
1472
     *
1473
     * @TODO Why is this necessary or desirable?
1474
     */
1475
0
    id = timer->source_id;
1476
0
    timer->source_id = 0;
1477
1478
0
    pcmk__trace("Invoking callbacks for timer %s", timer->name);
1479
1480
    // G_SOURCE_REMOVE is false; G_SOURCE_CONTINUE is true
1481
0
    if (!timer->cb(timer->user_data)) {
1482
0
        pcmk__trace("Timer %s complete", timer->name);
1483
0
        return G_SOURCE_REMOVE;
1484
0
    }
1485
1486
0
    timer->source_id = id;
1487
0
    return G_SOURCE_CONTINUE;
1488
0
}
1489
1490
/*!
1491
 * \internal
1492
 * \brief Start a main loop timer
1493
 *
1494
 * Starting a timer consists of:
1495
 * 1. stopping the timer if it's already running (by removing the associated
1496
 *    \c GSource)
1497
 * 2. creating a new \c GSource using \p timer->interval_ms as the timeout (see
1498
 *    \c pcmk__create_timer())
1499
 * 3. assigning the new \c GSource ID to \p timer->source_id
1500
 *
1501
 * \param[in,out] timer  Main loop timer
1502
 */
1503
void
1504
pcmk__main_loop_timer_start(pcmk__main_loop_timer_t *timer)
1505
0
{
1506
0
    CRM_CHECK((timer != NULL)
1507
0
              && (timer->interval_ms > 0)
1508
0
              && (timer->cb != NULL),
1509
0
              return);
1510
1511
0
    pcmk__main_loop_timer_stop(timer);
1512
1513
0
    pcmk__trace("Starting timer %s", timer->name);
1514
0
    timer->source_id = pcmk__create_timer(timer->interval_ms,
1515
0
                                          main_loop_timer_cb, timer);
1516
0
}
1517
1518
/*!
1519
 * \internal
1520
 * \brief Free a main loop timer
1521
 *
1522
 * \param[in,out] timer  Main loop timer
1523
 */
1524
void
1525
pcmk__main_loop_timer_free(pcmk__main_loop_timer_t *timer)
1526
0
{
1527
0
    if (timer == NULL) {
1528
0
        return;
1529
0
    }
1530
1531
0
    pcmk__trace("Destroying timer %s", timer->name);
1532
0
    pcmk__main_loop_timer_stop(timer);
1533
0
    free(timer->name);
1534
0
    free(timer);
1535
0
}
1536
1537
/*
1538
 * Helpers to make sure certain events aren't lost at shutdown
1539
 */
1540
1541
static gboolean
1542
drain_timeout_cb(void *user_data)
1543
0
{
1544
0
    bool *timeout_popped = (bool*) user_data;
1545
1546
0
    *timeout_popped = TRUE;
1547
0
    return G_SOURCE_REMOVE;
1548
0
}
1549
1550
/*!
1551
 * \brief Drain some remaining main loop events then quit it
1552
 *
1553
 * \param[in,out] mloop  Main loop to drain and quit
1554
 * \param[in]     n      Drain up to this many pending events
1555
 */
1556
void
1557
pcmk_quit_main_loop(GMainLoop *mloop, unsigned int n)
1558
0
{
1559
0
    if ((mloop != NULL) && g_main_loop_is_running(mloop)) {
1560
0
        GMainContext *ctx = g_main_loop_get_context(mloop);
1561
1562
        /* Drain up to n events in case some memory clean-up is pending
1563
         * (helpful to reduce noise in valgrind output).
1564
         */
1565
0
        for (int i = 0; (i < n) && g_main_context_pending(ctx); ++i) {
1566
0
            g_main_context_dispatch(ctx);
1567
0
        }
1568
0
        g_main_loop_quit(mloop);
1569
0
    }
1570
0
}
1571
1572
/*!
1573
 * \brief Process main loop events while a certain condition is met
1574
 *
1575
 * \param[in,out] mloop     Main loop to process
1576
 * \param[in]     timer_ms  Don't process longer than this amount of time
1577
 * \param[in]     check     Function that returns true if events should be
1578
 *                          processed
1579
 *
1580
 * \note This function is intended to be called at shutdown if certain important
1581
 *       events should not be missed. The caller would likely quit the main loop
1582
 *       or exit after calling this function. The check() function will be
1583
 *       passed the remaining timeout in milliseconds.
1584
 */
1585
void
1586
pcmk_drain_main_loop(GMainLoop *mloop, unsigned int timer_ms,
1587
                     bool (*check)(unsigned int))
1588
0
{
1589
0
    bool timeout_popped = FALSE;
1590
0
    unsigned int timer = 0;
1591
0
    GMainContext *ctx = NULL;
1592
1593
0
    CRM_CHECK(mloop && check, return);
1594
1595
0
    ctx = g_main_loop_get_context(mloop);
1596
0
    if (ctx) {
1597
0
        time_t start_time = time(NULL);
1598
1599
0
        timer = pcmk__create_timer(timer_ms, drain_timeout_cb, &timeout_popped);
1600
0
        while (!timeout_popped
1601
0
               && check(timer_ms - (time(NULL) - start_time) * 1000)) {
1602
0
            g_main_context_iteration(ctx, TRUE);
1603
0
        }
1604
0
    }
1605
0
    if (!timeout_popped && (timer > 0)) {
1606
0
        g_source_remove(timer);
1607
0
    }
1608
0
}
1609
1610
/*!
1611
 * \internal
1612
 * \brief Free data structures used for the mainloop
1613
 *
1614
 * \todo This is incomplete. Free other data structures created in this file.
1615
 */
1616
void
1617
mainloop_cleanup(void)
1618
0
{
1619
0
    g_list_free_full(child_list, free_main_loop_child);
1620
0
    child_list = NULL;
1621
1622
0
    g_clear_pointer(&gio_map, qb_array_free);
1623
1624
0
    for (int sig = 0; sig < NSIG; ++sig) {
1625
0
        mainloop_destroy_signal_entry(sig);
1626
0
    }
1627
0
}
1628
1629
// Deprecated functions kept only for backward API compatibility
1630
// LCOV_EXCL_START
1631
1632
#include <crm/common/mainloop_compat.h>
1633
1634
void
1635
mainloop_child_add_with_flags(pid_t pid, int timeout_ms, const char *desc,
1636
                              void *user_data,
1637
                              enum mainloop_child_flags flags,
1638
                              void (*callback)(mainloop_child_t *child, int core,
1639
                                               int signo, int exit_code))
1640
0
{
1641
0
    static bool need_init = true;
1642
1643
0
    mainloop_child_t *child = pcmk__assert_alloc(1, sizeof(mainloop_child_t));
1644
1645
0
    child->pid = pid;
1646
0
    child->desc = pcmk__str_copy(desc);
1647
0
    child->user_data = user_data;
1648
0
    child->kill_group = !pcmk__is_set(flags, mainloop_leave_pid_group);
1649
0
    child->callback = callback;
1650
1651
0
    if (timeout_ms > 0) {
1652
0
        child->timer_id = pcmk__create_timer(timeout_ms, child_timeout_callback,
1653
0
                                             child);
1654
0
    }
1655
1656
0
    child_list = g_list_append(child_list, child);
1657
1658
0
    if (need_init) {
1659
0
        need_init = false;
1660
0
        pcmk__create_timer(1, install_sigchld_handler, NULL);
1661
0
    }
1662
0
}
1663
1664
void
1665
mainloop_child_add(pid_t pid, int timeout_ms, const char *desc, void *user_data,
1666
                   void (*callback)(mainloop_child_t *child, int core,
1667
                                    int signo, int exit_code))
1668
0
{
1669
0
    mainloop_child_add_with_flags(pid, timeout_ms, desc, user_data, 0, callback);
1670
0
}
1671
1672
gboolean
1673
mainloop_child_kill(pid_t pid)
1674
0
{
1675
0
    const mainloop_child_t cmp_data = { .pid = pid };
1676
0
    GList *match = NULL;
1677
0
    mainloop_child_t *child = NULL;
1678
0
    int rc = pcmk_rc_ok;
1679
0
    bool no_hang = false;
1680
1681
0
    match = g_list_find_custom(child_list, &cmp_data, compare_children_by_pid);
1682
0
    if (match == NULL) {
1683
0
        return FALSE;
1684
0
    }
1685
1686
0
    child = match->data;
1687
1688
0
    rc = kill_child_pid(child);
1689
0
    if (rc == ESRCH) {
1690
0
        pcmk__trace("Waiting for signal that child process %lld completed",
1691
0
                    (long long) child->pid);
1692
0
        return TRUE;
1693
0
    }
1694
1695
0
    if (rc != pcmk_rc_ok) {
1696
0
        no_hang = true;
1697
0
    }
1698
1699
0
    return child_waitpid(match, no_hang)? TRUE : FALSE;
1700
0
}
1701
1702
pid_t
1703
mainloop_child_pid(mainloop_child_t *child)
1704
0
{
1705
0
    return child->pid;
1706
0
}
1707
1708
const char *
1709
mainloop_child_name(mainloop_child_t *child)
1710
0
{
1711
0
    return child->desc;
1712
0
}
1713
1714
int
1715
mainloop_child_timeout(mainloop_child_t *child)
1716
0
{
1717
0
    return child->timed_out? TRUE : FALSE;
1718
0
}
1719
1720
void *
1721
mainloop_child_userdata(mainloop_child_t *child)
1722
0
{
1723
0
    return child->user_data;
1724
0
}
1725
1726
void
1727
mainloop_clear_child_userdata(mainloop_child_t *child)
1728
0
{
1729
0
    child->user_data = NULL;
1730
0
}
1731
1732
struct mainloop_timer_s {
1733
    char *name;
1734
    unsigned int source_id;
1735
    unsigned int interval_ms;
1736
    bool repeat;
1737
    GSourceFunc cb;
1738
    void *user_data;
1739
};
1740
1741
static gboolean
1742
mainloop_timer_cb(void *user_data)
1743
0
{
1744
0
    int id = 0;
1745
0
    mainloop_timer_t *timer = user_data;
1746
1747
0
    pcmk__assert((timer != NULL) && (timer->cb != NULL));
1748
1749
0
    id = timer->source_id;
1750
0
    timer->source_id = 0;
1751
1752
0
    pcmk__trace("Invoking callbacks for timer %s", timer->name);
1753
1754
0
    if (!timer->cb(timer->user_data)) {
1755
0
        pcmk__trace("Timer %s complete", timer->name);
1756
0
        return G_SOURCE_REMOVE;
1757
0
    }
1758
1759
0
    if (!timer->repeat) {
1760
0
        return G_SOURCE_REMOVE;
1761
0
    }
1762
1763
0
    timer->source_id = id;
1764
0
    return G_SOURCE_CONTINUE;
1765
0
}
1766
1767
bool
1768
mainloop_timer_running(mainloop_timer_t *timer)
1769
0
{
1770
0
    return (timer != NULL) && (timer->source_id != 0);
1771
0
}
1772
1773
void
1774
mainloop_timer_start(mainloop_timer_t *timer)
1775
0
{
1776
0
    mainloop_timer_stop(timer);
1777
1778
0
    if ((timer == NULL) || (timer->interval_ms == 0) || (timer->cb == NULL)) {
1779
0
        return;
1780
0
    }
1781
1782
0
    pcmk__trace("Starting timer %s", timer->name);
1783
0
    timer->source_id = pcmk__create_timer(timer->interval_ms, mainloop_timer_cb,
1784
0
                                          timer);
1785
0
}
1786
1787
void
1788
mainloop_timer_stop(mainloop_timer_t *timer)
1789
0
{
1790
0
    if ((timer == NULL) || (timer->source_id == 0)) {
1791
0
        return;
1792
0
    }
1793
1794
0
    pcmk__trace("Stopping timer %s", timer->name);
1795
0
    g_source_remove(timer->source_id);
1796
0
    timer->source_id = 0;
1797
0
}
1798
1799
unsigned int
1800
mainloop_timer_set_period(mainloop_timer_t *timer, unsigned int interval_ms)
1801
0
{
1802
0
    unsigned int last = 0;
1803
1804
0
    if (timer == NULL) {
1805
0
        return 0;
1806
0
    }
1807
1808
0
    last = timer->interval_ms;
1809
0
    timer->interval_ms = interval_ms;
1810
1811
0
    if ((timer->source_id != 0) && (timer->interval_ms != last)) {
1812
0
        mainloop_timer_start(timer);
1813
0
    }
1814
1815
0
    return last;
1816
0
}
1817
1818
mainloop_timer_t *
1819
mainloop_timer_add(const char *name, unsigned int interval_ms, bool repeat,
1820
                   GSourceFunc cb, void *userdata)
1821
0
{
1822
0
    mainloop_timer_t *timer = pcmk__assert_alloc(1, sizeof(mainloop_timer_t));
1823
1824
0
    if (name != NULL) {
1825
0
        timer->name = pcmk__assert_asprintf("%s-%u-%d", name, interval_ms,
1826
0
                                            repeat);
1827
1828
0
    } else {
1829
0
        timer->name = pcmk__assert_asprintf("%p-%u-%d", timer, interval_ms,
1830
0
                                            repeat);
1831
0
    }
1832
1833
0
    timer->interval_ms = interval_ms;
1834
0
    timer->repeat = repeat;
1835
0
    timer->cb = cb;
1836
0
    timer->user_data = userdata;
1837
1838
0
    pcmk__trace("Created timer %s with %p", timer->name, userdata);
1839
0
    return timer;
1840
0
}
1841
1842
void
1843
mainloop_timer_del(mainloop_timer_t *timer)
1844
0
{
1845
0
    if (timer == NULL) {
1846
0
        return;
1847
0
    }
1848
1849
0
    pcmk__trace("Destroying timer %s", timer->name);
1850
0
    mainloop_timer_stop(timer);
1851
0
    free(timer->name);
1852
0
    free(timer);
1853
0
}
1854
1855
// LCOV_EXCL_STOP
1856
// End deprecated API