1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
/*
* Copyright 2009-2025 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU Lesser General Public License
* version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
*/
#ifndef PCMK__CRM_COMMON_MAINLOOP__H
#define PCMK__CRM_COMMON_MAINLOOP__H
#include <stdbool.h> // bool
#include <signal.h> // sighandler_t
#include <sys/types.h> // pid_t, ssize_t
#include <glib.h> // gpointer, gboolean, guint, GSourceFunc, GMainLoop
#include <qb/qbipcs.h> // qb_ipcs_service_t, etc.
#include <crm/common/ipc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file
* \brief Wrappers for and extensions to glib mainloop
* \ingroup core
*/
enum mainloop_child_flags {
/* don't kill pid group on timeout, only kill the pid */
mainloop_leave_pid_group = 0x01,
};
// NOTE: sbd (as of at least 1.5.2) uses this
typedef struct trigger_s crm_trigger_t;
typedef struct mainloop_io_s mainloop_io_t;
typedef struct mainloop_child_s mainloop_child_t;
// NOTE: sbd (as of at least 1.5.2) uses this
typedef struct mainloop_timer_s mainloop_timer_t;
void mainloop_cleanup(void);
// NOTE: sbd (as of at least 1.5.2) uses this
crm_trigger_t *mainloop_add_trigger(int priority, int (*dispatch) (gpointer user_data),
gpointer userdata);
// NOTE: sbd (as of at least 1.5.2) uses this
void mainloop_set_trigger(crm_trigger_t * source);
void mainloop_trigger_complete(crm_trigger_t * trig);
gboolean mainloop_destroy_trigger(crm_trigger_t * source);
#ifndef HAVE_SIGHANDLER_T
typedef void (*sighandler_t)(int);
#endif
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch);
// NOTE: sbd (as of at least 1.5.2) uses this
gboolean mainloop_add_signal(int sig, void (*dispatch) (int sig));
gboolean mainloop_destroy_signal(int sig);
bool mainloop_timer_running(mainloop_timer_t *t);
// NOTE: sbd (as of at least 1.5.2) uses this
void mainloop_timer_start(mainloop_timer_t *t);
// NOTE: sbd (as of at least 1.5.2) uses this
void mainloop_timer_stop(mainloop_timer_t *t);
guint mainloop_timer_set_period(mainloop_timer_t *t, guint period_ms);
// NOTE: sbd (as of at least 1.5.2) uses this
mainloop_timer_t *mainloop_timer_add(const char *name, guint period_ms, bool repeat, GSourceFunc cb, void *userdata);
void mainloop_timer_del(mainloop_timer_t *t);
struct ipc_client_callbacks {
/*!
* \brief Dispatch function for an IPC connection used as mainloop source
*
* \param[in] buffer Message read from IPC connection
* \param[in] length Number of bytes in \p buffer
* \param[in] userdata User data passed when creating mainloop source
*
* \return Negative value to remove source, anything else to keep it
*/
int (*dispatch) (const char *buffer, ssize_t length, gpointer userdata);
/*!
* \brief Destroy function for mainloop IPC connection client data
*
* \param[in,out] userdata User data passed when creating mainloop source
*/
void (*destroy) (gpointer userdata);
};
qb_ipcs_service_t *mainloop_add_ipc_server(const char *name, enum qb_ipc_type type,
struct qb_ipcs_service_handlers *callbacks);
/*!
* \brief Start server-side API end-point, hooked into the internal event loop
*
* \param[in] name name of the IPC end-point ("address" for the client)
* \param[in] type selects libqb's IPC back-end (or use #QB_IPC_NATIVE)
* \param[in] callbacks defines libqb's IPC service-level handlers
* \param[in] priority priority relative to other events handled in the
* abstract handling loop, use #QB_LOOP_MED when unsure
*
* \return libqb's opaque handle to the created service abstraction
*
* \note For portability concerns, do not use this function if you keep
* \p priority as #QB_LOOP_MED, stick with #mainloop_add_ipc_server
* (with exactly such semantics) instead (once you link with this new
* symbol employed, you can't downgrade the library freely anymore).
*
* \note The intended effect will only get fully reflected when run-time
* linked to patched libqb: https://github.com/ClusterLabs/libqb/pull/352
*/
qb_ipcs_service_t *mainloop_add_ipc_server_with_prio(const char *name,
enum qb_ipc_type type,
struct qb_ipcs_service_handlers *callbacks,
enum qb_loop_priority prio);
void mainloop_del_ipc_server(qb_ipcs_service_t * server);
// @COMPAT max_size parameter is deprecated and unused since 3.0.1
mainloop_io_t *mainloop_add_ipc_client(const char *name, int priority, size_t max_size,
void *userdata, struct ipc_client_callbacks *callbacks);
void mainloop_del_ipc_client(mainloop_io_t * client);
crm_ipc_t *mainloop_get_ipc_client(mainloop_io_t * client);
struct mainloop_fd_callbacks {
/*!
* \brief Dispatch function for mainloop file descriptor with data ready
*
* \param[in,out] userdata User data passed when creating mainloop source
*
* \return Negative value to remove source, anything else to keep it
*/
int (*dispatch) (gpointer userdata);
/*!
* \brief Destroy function for mainloop file descriptor client data
*
* \param[in,out] userdata User data passed when creating mainloop source
*/
void (*destroy) (gpointer userdata);
};
mainloop_io_t *mainloop_add_fd(const char *name, int priority, int fd, void *userdata,
struct mainloop_fd_callbacks *callbacks);
void mainloop_del_fd(mainloop_io_t * client);
/*
* Create a new tracked process
* To track a process group, use -pid
*/
void mainloop_child_add(pid_t pid,
int timeout,
const char *desc,
void *userdata,
void (*callback) (mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode));
void mainloop_child_add_with_flags(pid_t pid,
int timeout,
const char *desc,
void *userdata,
enum mainloop_child_flags,
void (*callback) (mainloop_child_t * p, pid_t pid, int core, int signo, int exitcode));
void *mainloop_child_userdata(mainloop_child_t * child);
int mainloop_child_timeout(mainloop_child_t * child);
const char *mainloop_child_name(mainloop_child_t * child);
pid_t mainloop_child_pid(mainloop_child_t * child);
void mainloop_clear_child_userdata(mainloop_child_t * child);
gboolean mainloop_child_kill(pid_t pid);
void pcmk_quit_main_loop(GMainLoop *mloop, unsigned int n);
void pcmk_drain_main_loop(GMainLoop *mloop, guint timer_ms,
bool (*check)(guint));
#define G_PRIORITY_MEDIUM (G_PRIORITY_HIGH/2)
#ifdef __cplusplus
}
#endif
#endif
|