Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d629ce3
Refactor: daemons: Split up IPC code in execd.
clumens Dec 18, 2025
462e7ab
Refactor: daemons: Rename functions in execd_ipc.c.
clumens Dec 18, 2025
c83f351
Refactor: daemons: Standardize functions in execd_ipc.c.
clumens Dec 18, 2025
7acc4f3
Refactor: daemons: Standardize handling IPC requests in execd.
clumens Dec 18, 2025
b436713
Refactor: libcrmcommon: Add pcmk__serve_execd_ipc.
clumens Dec 18, 2025
d4d378b
Refactor: daemons: Standardize execd IPC startup/shutdown.
clumens Dec 18, 2025
7f48b4f
Refactor: daemons: Add some additional checks to execd_ipc_dispatch.
clumens Jan 6, 2026
5f45273
Refactor: daemons: Standardize functions in remoted_proxy.c.
clumens Jan 6, 2026
287c0fa
Refactor: daemons: Clean up header blocks in some of execd.
clumens Jan 6, 2026
1dda700
Low: daemons: Clean up XML memory in IPC dispatch functions.
clumens Jan 8, 2026
bba01e1
Refactor: libcrmcommon: Standardize IPC startup failure messages.
clumens Jan 8, 2026
a23270f
Low: daemons: Set ipc_flags in lrmd_remote_client_msg to 0.
clumens Jan 8, 2026
7f82ca1
Refactor: daemons: Remove check on client->id from execd_ipc_dispatch.
clumens Jan 8, 2026
0c2b94b
Refactor: daemons: Don't call _unregister_handlers from _ipc_cleanup.
clumens Jan 8, 2026
74852a8
Refactor: daemons: Use g_clear_pointer in IPC cleanup functions.
clumens Jan 8, 2026
1eb3aca
Refactor: daemons: Use g_clear_pointer in ipc_proxy_cleanup.
clumens Jan 8, 2026
69411f2
Low: daemons: Use crm_ipc_client_response in lrmd_remote_client_msg.
clumens Jan 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions daemons/attrd/attrd_corosync.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2025 the Pacemaker project contributors
* Copyright 2013-2026 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -95,7 +95,7 @@ attrd_peer_message(pcmk__node_status_t *peer, xmlNode *xml)
pcmk__request_t request = {
.ipc_client = NULL,
.ipc_id = 0,
.ipc_flags = 0,
.ipc_flags = crm_ipc_flags_none,
.peer = peer->name,
.xml = xml,
.call_options = 0,
Expand Down
13 changes: 8 additions & 5 deletions daemons/attrd/attrd_ipc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2025 the Pacemaker project contributors
* Copyright 2004-2026 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -615,11 +615,12 @@ attrd_ipc_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
pcmk__update_acl_user(xml, PCMK__XA_ATTR_USER, client->user);

request.op = pcmk__xe_get_copy(request.xml, PCMK_XA_TASK);
CRM_CHECK(request.op != NULL, return 0);
CRM_CHECK(request.op != NULL, goto done);

attrd_handle_request(&request);
}

done:
pcmk__xml_free(xml);
return 0;
}
Expand All @@ -632,16 +633,18 @@ static struct qb_ipcs_service_handlers ipc_callbacks = {
.connection_destroyed = attrd_ipc_destroy
};

/*!
* \internal
* \brief Clean up attrd IPC communication
*/
void
attrd_ipc_cleanup(void)
{
if (ipcs != NULL) {
pcmk__drop_all_clients(ipcs);
qb_ipcs_destroy(ipcs);
ipcs = NULL;
g_clear_pointer(&ipcs, qb_ipcs_destroy);
}

attrd_unregister_handlers();
pcmk__client_cleanup();
}

Expand Down
3 changes: 2 additions & 1 deletion daemons/attrd/pacemaker-attrd.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2025 the Pacemaker project contributors
* Copyright 2013-2026 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
Expand Down Expand Up @@ -202,6 +202,7 @@ main(int argc, char **argv)
attrd_free_removed_peers();
attrd_free_waitlist();
attrd_cluster_disconnect();
attrd_unregister_handlers();
g_hash_table_destroy(attributes);
}

Expand Down
1 change: 1 addition & 0 deletions daemons/execd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pacemaker_execd_LDADD += $(top_builddir)/lib/common/libcrmcommon.la
pacemaker_execd_SOURCES = pacemaker-execd.c
pacemaker_execd_SOURCES += execd_commands.c
pacemaker_execd_SOURCES += execd_alerts.c
pacemaker_execd_SOURCES += execd_ipc.c
pacemaker_execd_SOURCES += execd_messages.c

sbin_PROGRAMS = pacemaker-remoted
Expand Down
227 changes: 227 additions & 0 deletions daemons/execd/execd_ipc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* Copyright 2012-2026 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.
*/

#include <crm_internal.h>

#include <errno.h> // ENOMEM
#include <stddef.h> // NULL, size_t
#include <stdint.h> // int32_t, uint32_t
#include <sys/types.h> // gid_t, uid_t

#include <glib.h> // g_byte_array_free, TRUE
#include <libxml/tree.h> // xmlNode
#include <qb/qbipcs.h> // qb_ipcs_connection_t

#include <crm/common/internal.h> // pcmk__client_t, pcmk__find_client
#include <crm/common/ipc.h> // crm_ipc_client_response
#include <crm/common/logging.h> // CRM_CHECK
#include <crm/common/results.h> // pcmk_rc_*, pcmk_rc_str

#include "pacemaker-execd.h" // client_disconnect_cleanup

static qb_ipcs_service_t *ipcs = NULL;

/*!
* \internal
* \brief Accept a new client IPC connection
*
* \param[in,out] c New connection
* \param[in] uid Client user id
* \param[in] gid Client group id
*
* \return 0 on success, -errno otherwise
*/
static int32_t
execd_ipc_accept(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
{
pcmk__trace("New client connection %p", c);
if (pcmk__new_client(c, uid, gid) == NULL) {
return -ENOMEM;
}
return 0;
}

/*!
* \internal
* \brief Handle a newly created connection
*
* \param[in,out] c New connection
*/
static void
execd_ipc_created(qb_ipcs_connection_t *c)
{
pcmk__client_t *new_client = pcmk__find_client(c);

pcmk__trace("New client connection %p", c);
pcmk__assert(new_client != NULL);
/* Now that the connection is offically established, alert
* the other clients a new connection exists. */

notify_of_new_client(new_client);
}

/*!
* \internal
* \brief Destroy a client IPC connection
*
* \param[in] c Connection to destroy
*
* \return 0 (i.e. do not re-run this callback)
*/
static int32_t
execd_ipc_closed(qb_ipcs_connection_t *c)
{
pcmk__client_t *client = pcmk__find_client(c);

if (client == NULL) {
pcmk__trace("Ignoring request to clean up unknown connection %p", c);
} else {
pcmk__trace("Cleaning up closed client connection %p", c);
client_disconnect_cleanup(client->id);
#ifdef PCMK__COMPILE_REMOTE
ipc_proxy_remove_provider(client);
#endif
lrmd_client_destroy(client);
}

return 0;
}

/*!
* \internal
* \brief Destroy a client IPC connection
*
* \param[in] c Connection to destroy
*
* \note We handle a destroyed connection the same as a closed one,
* but we need a separate handler because the return type is different.
*/
static void
execd_ipc_destroy(qb_ipcs_connection_t *c)
{
pcmk__trace("Destroying client connection %p", c);
execd_ipc_closed(c);
}

/*!
* \internal
* \brief Handle a message from an IPC connection
*
* \param[in,out] c Established IPC connection
* \param[in] data The message data read from the connection - this can be
* a complete IPC message or just a part of one if it's
* very large
* \param[size] size Unused
*
* \return 0 in all cases
*/
static int32_t
execd_ipc_dispatch(qb_ipcs_connection_t *c, void *data, size_t size)
{
int rc = pcmk_rc_ok;
uint32_t id = 0;
uint32_t flags = 0;
pcmk__client_t *client = pcmk__find_client(c);
xmlNode *msg = NULL;

// Sanity-check, and parse XML from IPC data
CRM_CHECK(client != NULL, return 0);

if (data == NULL) {
pcmk__debug("No IPC data from PID %d", pcmk__client_pid(c));
return 0;
}

rc = pcmk__ipc_msg_append(&client->buffer, data);

if (rc == pcmk_rc_ipc_more) {
/* We haven't read the complete message yet, so just return. */
return 0;

} else if (rc == pcmk_rc_ok) {
/* We've read the complete message and there's already a header on
* the front. Pass it off for processing.
*/
msg = pcmk__client_data2xml(client, &id, &flags);
g_byte_array_free(client->buffer, TRUE);
client->buffer = NULL;

} else {
/* Some sort of error occurred reassembling the message. All we can
* do is clean up, log an error and return.
*/
pcmk__err("Error when reading IPC message: %s", pcmk_rc_str(rc));

if (client->buffer != NULL) {
g_byte_array_free(client->buffer, TRUE);
client->buffer = NULL;
}

return 0;
}

CRM_CHECK(pcmk__is_set(flags, crm_ipc_client_response), goto done);

if ((msg == NULL) || execd_invalid_msg(msg)) {
pcmk__debug("Unrecognizable IPC data from PID %d", pcmk__client_pid(c));
pcmk__ipc_send_ack(client, id, flags, PCMK__XE_NACK, NULL, CRM_EX_PROTOCOL);
} else {
pcmk__request_t request = {
.ipc_client = client,
.ipc_id = id,
.ipc_flags = flags,
.peer = NULL,
.xml = msg,
.call_options = 0,
.result = PCMK__UNKNOWN_RESULT,
};

request.op = pcmk__xe_get_copy(request.xml, PCMK__XA_LRMD_OP);
CRM_CHECK(request.op != NULL, goto done);

execd_handle_request(&request);
}

done:
pcmk__xml_free(msg);
return 0;
}

static struct qb_ipcs_service_handlers ipc_callbacks = {
.connection_accept = execd_ipc_accept,
.connection_created = execd_ipc_created,
.msg_process = execd_ipc_dispatch,
.connection_closed = execd_ipc_closed,
.connection_destroyed = execd_ipc_destroy
};

/*!
* \internal
* \brief Clean up executor IPC communication
*/
void
execd_ipc_cleanup(void)
{
if (ipcs != NULL) {
pcmk__drop_all_clients(ipcs);
g_clear_pointer(&ipcs, qb_ipcs_destroy);
}

pcmk__client_cleanup();
}

/*!
* \internal
* \brief Set up executor IPC communication
*/
void
execd_ipc_init(void)
{
pcmk__serve_execd_ipc(&ipcs, &ipc_callbacks);
}
Loading