• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eclipse-bluechi / bluechi / 16743008054

05 Aug 2025 07:02AM UTC coverage: 78.083% (+7.4%) from 70.652%
16743008054

push

github

engelmi
Added pypi release section to maintainer readme

Signed-off-by: Michael Engel <mengel@redhat.com>

5369 of 6876 relevant lines covered (78.08%)

991.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.89
/src/controller/monitor.c
1
/*
2
 * Copyright Contributors to the Eclipse BlueChi project
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
#include "libbluechi/log/log.h"
7

8
#include "controller.h"
9
#include "job.h"
10
#include "monitor.h"
11
#include "node.h"
12

13
#include "libbluechi/bus/utils.h"
14

15
/****************************************
16
 ********** Subscription ****************
17
 ****************************************/
18

19
Subscription *subscription_new(const char *node) {
14✔
20
        static uint32_t next_id = 1;
14✔
21

22
        _cleanup_subscription_ Subscription *subscription = malloc0(sizeof(Subscription));
28✔
23
        if (subscription == NULL) {
14✔
24
                return NULL;
25
        }
26

27
        subscription->ref_count = 1;
14✔
28
        subscription->id = ++next_id;
14✔
29
        LIST_INIT(subscriptions, subscription);
14✔
30
        LIST_INIT(all_subscriptions, subscription);
14✔
31
        LIST_HEAD_INIT(subscription->subscribed_units);
14✔
32

33
        subscription->node = strdup(node);
14✔
34
        if (subscription->node == NULL) {
14✔
35
                return NULL;
×
36
        }
37

38
        return steal_pointer(&subscription);
39
}
40

41
Subscription *create_monitor_subscription(Monitor *monitor, const char *node) {
9✔
42
        Subscription *subscription = subscription_new(node);
9✔
43
        if (subscription == NULL) {
9✔
44
                return NULL;
45
        }
46

47
        subscription->monitor = monitor_ref(monitor);
9✔
48
        subscription->free_monitor = (free_func_t) monitor_unref;
9✔
49

50
        subscription->handle_unit_new = monitor_on_unit_new;
9✔
51
        subscription->handle_unit_removed = monitor_on_unit_removed;
9✔
52
        subscription->handle_unit_state_changed = monitor_on_unit_state_changed;
9✔
53
        subscription->handle_unit_property_changed = monitor_on_unit_property_changed;
9✔
54

55
        return subscription;
9✔
56
}
57

58
bool subscription_add_unit(Subscription *sub, const char *unit) {
15✔
59
        char *unit_copy = NULL;
15✔
60
        if (!copy_str(&unit_copy, unit)) {
15✔
61
                return false;
15✔
62
        }
63

64
        SubscribedUnit *su = malloc0(sizeof(SubscribedUnit));
15✔
65
        if (su == NULL) {
15✔
66
                free(unit_copy);
×
67
                return false;
×
68
        }
69
        su->name = unit_copy;
15✔
70
        LIST_APPEND(units, sub->subscribed_units, su);
15✔
71

72
        return true;
73
}
74

75
bool subscription_has_node_wildcard(Subscription *sub) {
26✔
76
        return sub->node != NULL && streq(sub->node, SYMBOL_WILDCARD);
26✔
77
}
78

79
Subscription *subscription_ref(Subscription *subscription) {
22✔
80
        subscription->ref_count++;
22✔
81
        return subscription;
22✔
82
}
83

84
void subscription_unref(Subscription *subscription) {
36✔
85
        subscription->ref_count--;
36✔
86
        if (subscription->ref_count != 0) {
36✔
87
                return;
88
        }
89

90
        if (subscription->free_monitor) {
14✔
91
                subscription->free_monitor(subscription->monitor);
9✔
92
        }
93

94
        SubscribedUnit *su = NULL;
14✔
95
        SubscribedUnit *next_su = NULL;
14✔
96
        LIST_FOREACH_SAFE(units, su, next_su, subscription->subscribed_units) {
29✔
97
                LIST_REMOVE(units, subscription->subscribed_units, su);
15✔
98
                free_and_null(su->name);
15✔
99
                free_and_null(su);
15✔
100
        }
101

102
        free_and_null(subscription->node);
14✔
103
        free_and_null(subscription);
14✔
104
}
105

106

107
/***********************************
108
 ********** Monitor ****************
109
 ***********************************/
110

111
static int monitor_method_close(sd_bus_message *m, void *userdata, sd_bus_error *ret_error);
112
static int monitor_method_subscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
113
static int monitor_method_subscribe_list(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
114
static int monitor_method_unsubscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
115
static int monitor_method_add_peer(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
116
static int monitor_method_remove_peer(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error);
117

118
static void monitor_emit_peer_removed(void *userdata, MonitorPeer *peer, const char *reason);
119

120
static const sd_bus_vtable monitor_vtable[] = {
121
        SD_BUS_VTABLE_START(0),
122
        SD_BUS_METHOD("Subscribe", "ss", "u", monitor_method_subscribe, 0),
123
        SD_BUS_METHOD("SubscribeList", "sas", "u", monitor_method_subscribe_list, 0),
124
        SD_BUS_METHOD("Unsubscribe", "u", "", monitor_method_unsubscribe, 0),
125
        SD_BUS_METHOD("AddPeer", "s", "u", monitor_method_add_peer, 0),
126
        SD_BUS_METHOD("RemovePeer", "us", "", monitor_method_remove_peer, 0),
127
        SD_BUS_METHOD("Close", "", "", monitor_method_close, 0),
128
        SD_BUS_SIGNAL_WITH_NAMES(
129
                        "UnitPropertiesChanged",
130
                        "sssa{sv}",
131
                        SD_BUS_PARAM(node) SD_BUS_PARAM(unit) SD_BUS_PARAM(interface) SD_BUS_PARAM(properties),
132
                        0),
133
        SD_BUS_SIGNAL_WITH_NAMES("UnitNew", "ss", SD_BUS_PARAM(node) SD_BUS_PARAM(unit), 0),
134
        SD_BUS_SIGNAL_WITH_NAMES(
135
                        "UnitStateChanged",
136
                        "sssss",
137
                        SD_BUS_PARAM(node) SD_BUS_PARAM(unit) SD_BUS_PARAM(active_state)
138
                                        SD_BUS_PARAM(substate) SD_BUS_PARAM(reason),
139
                        0),
140
        SD_BUS_SIGNAL_WITH_NAMES("UnitRemoved", "ss", SD_BUS_PARAM(node) SD_BUS_PARAM(unit), 0),
141
        SD_BUS_SIGNAL_WITH_NAMES("PeerRemoved", "s", SD_BUS_PARAM(reason), 0),
142
        SD_BUS_VTABLE_END
143
};
144

145
Monitor *monitor_new(Controller *controller, const char *owner) {
9✔
146
        static uint32_t next_id = 0;
9✔
147
        _cleanup_monitor_ Monitor *monitor = malloc0(sizeof(Monitor));
9✔
148
        if (monitor == NULL) {
9✔
149
                return NULL;
150
        }
151

152
        monitor->ref_count = 1;
9✔
153
        monitor->id = ++next_id;
9✔
154
        monitor->controller = controller;
9✔
155
        LIST_INIT(monitors, monitor);
9✔
156
        LIST_HEAD_INIT(monitor->subscriptions);
9✔
157
        LIST_HEAD_INIT(monitor->peers);
9✔
158

159
        monitor->owner = strdup(owner);
9✔
160
        if (monitor->owner == NULL) {
9✔
161
                return NULL;
162
        }
163

164
        int r = asprintf(&monitor->object_path, "%s/%u", MONITOR_OBJECT_PATH_PREFIX, monitor->id);
9✔
165
        if (r < 0) {
9✔
166
                return NULL;
167
        }
168

169
        return steal_pointer(&monitor);
170
}
171

172
Monitor *monitor_ref(Monitor *monitor) {
18✔
173
        monitor->ref_count++;
18✔
174
        return monitor;
18✔
175
}
176

177
void monitor_unref(Monitor *monitor) {
27✔
178
        monitor->ref_count--;
27✔
179
        if (monitor->ref_count != 0) {
27✔
180
                return;
181
        }
182

183
        sd_bus_slot_unrefp(&monitor->export_slot);
9✔
184
        free_and_null(monitor->object_path);
9✔
185
        free_and_null(monitor->owner);
9✔
186
        free_and_null(monitor);
9✔
187
}
188

189
bool monitor_export(Monitor *monitor) {
9✔
190
        Controller *controller = monitor->controller;
9✔
191

192
        int r = sd_bus_add_object_vtable(
18✔
193
                        controller->api_bus,
194
                        &monitor->export_slot,
195
                        monitor->object_path,
9✔
196
                        MONITOR_INTERFACE,
197
                        monitor_vtable,
198
                        monitor);
199
        if (r < 0) {
9✔
200
                bc_log_errorf("Failed to add monitor vtable: %s", strerror(-r));
×
201
                return false;
×
202
        }
203

204
        return true;
205
}
206

207
void monitor_close(Monitor *monitor) {
9✔
208
        Controller *controller = monitor->controller;
9✔
209

210
        Subscription *sub = NULL;
9✔
211
        Subscription *next_sub = NULL;
9✔
212
        LIST_FOREACH_SAFE(subscriptions, sub, next_sub, monitor->subscriptions) {
17✔
213
                controller_remove_subscription(controller, sub);
8✔
214
                LIST_REMOVE(subscriptions, monitor->subscriptions, sub);
8✔
215
                subscription_unref(sub);
8✔
216
        }
217

218
        MonitorPeer *peer = NULL;
9✔
219
        MonitorPeer *next_peer = NULL;
9✔
220
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
11✔
221
                monitor_emit_peer_removed(monitor, peer, "monitor closed");
2✔
222
                LIST_REMOVE(peers, monitor->peers, peer);
2✔
223
                free_and_null(peer->name);
2✔
224
                free_and_null(peer);
2✔
225
        }
226

227
        sd_bus_slot_unrefp(&monitor->export_slot);
9✔
228
        monitor->export_slot = NULL;
9✔
229
}
9✔
230

231
/***********************************************************
232
 *** org.eclipse.bluechi.Monitor.Close *********************
233
 ***********************************************************/
234

235
static int monitor_method_close(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
×
236
        _cleanup_monitor_ Monitor *monitor = monitor_ref(userdata);
×
237
        Controller *controller = monitor->controller;
×
238

239
        /* Ensure we don't close it twice somehow */
240
        if (monitor->export_slot == NULL) {
×
241
                return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_FAILED, "Monitor already closed");
×
242
        }
243

244
        monitor_close(monitor);
×
245
        controller_remove_monitor(controller, monitor);
×
246

247
        return sd_bus_reply_method_return(m, "");
×
248
}
249

250
/***********************************************************
251
 *** org.eclipse.bluechi.Monitor.Subscribe *****************
252
 ***********************************************************/
253

254
static int monitor_method_subscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
7✔
255
        Monitor *monitor = userdata;
7✔
256
        Controller *controller = monitor->controller;
7✔
257
        const char *node = NULL;
7✔
258
        const char *unit = NULL;
7✔
259

260
        int r = sd_bus_message_read(m, "ss", &node, &unit);
7✔
261
        if (r < 0) {
7✔
262
                return sd_bus_reply_method_errorf(
×
263
                                m,
264
                                SD_BUS_ERROR_INVALID_ARGS,
265
                                "Invalid argument for the node or the unit: %s",
266
                                strerror(-r));
267
        }
268

269
        _cleanup_subscription_ Subscription *sub = create_monitor_subscription(monitor, node);
14✔
270
        if (sub == NULL) {
7✔
271
                return sd_bus_reply_method_errorf(
×
272
                                m,
273
                                SD_BUS_ERROR_FAILED,
274
                                "Failed to create a monitor subscription: %s",
275
                                strerror(-r));
276
        }
277

278
        if (!subscription_add_unit(sub, unit)) {
7✔
279
                return sd_bus_reply_method_errorf(
×
280
                                m, SD_BUS_ERROR_FAILED, "Failed to add an unit to a subscription");
281
        }
282

283
        LIST_APPEND(subscriptions, monitor->subscriptions, subscription_ref(sub));
7✔
284
        controller_add_subscription(controller, sub);
7✔
285

286
        return sd_bus_reply_method_return(m, "u", sub->id);
7✔
287
}
288

289
/***********************************************************
290
 ***** org.eclipse.bluechi.Monitor.SubscribeList ***********
291
 ***********************************************************/
292

293
static int monitor_method_subscribe_list(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
2✔
294
        Monitor *monitor = userdata;
2✔
295
        Controller *controller = monitor->controller;
2✔
296

297
        const char *node = NULL;
2✔
298
        int r = sd_bus_message_read(m, "s", &node);
2✔
299
        if (r < 0) {
2✔
300
                return sd_bus_reply_method_errorf(
×
301
                                m,
302
                                SD_BUS_ERROR_INVALID_ARGS,
303
                                "Invalid argument for the node name: %s",
304
                                strerror(-r));
305
        }
306

307
        _cleanup_subscription_ Subscription *sub = create_monitor_subscription(monitor, node);
4✔
308
        if (sub == NULL) {
2✔
309
                return sd_bus_reply_method_errorf(
×
310
                                m,
311
                                SD_BUS_ERROR_FAILED,
312
                                "Failed to create a monitor subscription: %s",
313
                                strerror(-r));
314
        }
315

316
        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
2✔
317
        if (r < 0) {
2✔
318
                return sd_bus_reply_method_errorf(
×
319
                                m,
320
                                SD_BUS_ERROR_INVALID_ARGS,
321
                                "Invalid argument for an array of unit : %s",
322
                                strerror(-r));
323
        }
324

325
        while (sd_bus_message_at_end(m, false) == 0) {
5✔
326
                const char *unit = NULL;
3✔
327
                r = sd_bus_message_read(m, "s", &unit);
3✔
328
                if (r < 0) {
3✔
329
                        return sd_bus_reply_method_errorf(
×
330
                                        m,
331
                                        SD_BUS_ERROR_INVALID_ARGS,
332
                                        "Invalid arguments for units: %s",
333
                                        strerror(-r));
334
                }
335

336
                if (!subscription_add_unit(sub, unit)) {
3✔
337
                        return sd_bus_reply_method_errorf(
×
338
                                        m,
339
                                        SD_BUS_ERROR_FAILED,
340
                                        "Internal error when adding unit '%s' to subscription",
341
                                        unit);
342
                }
343
        }
344

345
        r = sd_bus_message_exit_container(m);
2✔
346
        if (r < 0) {
2✔
347
                return sd_bus_reply_method_errorf(
×
348
                                m,
349
                                SD_BUS_ERROR_FAILED,
350
                                "Failed to exit message container while processing unit subscription: %s",
351
                                strerror(-r));
352
        }
353

354
        LIST_APPEND(subscriptions, monitor->subscriptions, subscription_ref(sub));
2✔
355
        controller_add_subscription(controller, sub);
2✔
356

357
        return sd_bus_reply_method_return(m, "u", sub->id);
2✔
358
}
359

360
/***********************************************************
361
 ********* org.eclipse.bluechi.Monitor.Unsubscribe *********
362
 ***********************************************************/
363

364
static Subscription *monitor_find_subscription(Monitor *monitor, uint32_t sub_id) {
1✔
365
        Subscription *sub = NULL;
1✔
366
        Subscription *next_sub = NULL;
1✔
367
        LIST_FOREACH_SAFE(subscriptions, sub, next_sub, monitor->subscriptions) {
1✔
368
                if (sub->id == sub_id) {
1✔
369
                        return sub;
370
                }
371
        }
372
        bc_log_debugf("Subscription ID '%d' for monitor '%s' not found", sub_id, monitor->object_path);
×
373

374
        return NULL;
×
375
}
376

377
static int monitor_method_unsubscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
1✔
378
        Monitor *monitor = userdata;
1✔
379
        Controller *controller = monitor->controller;
1✔
380
        uint32_t sub_id = 0;
1✔
381

382
        int r = sd_bus_message_read(m, "u", &sub_id);
1✔
383
        if (r < 0) {
1✔
384
                return sd_bus_reply_method_errorf(
×
385
                                m,
386
                                SD_BUS_ERROR_INVALID_ARGS,
387
                                "Invalid arguments for the subscription ID: %s",
388
                                strerror(-r));
389
        }
390

391
        Subscription *sub = monitor_find_subscription(monitor, sub_id);
1✔
392
        if (sub == NULL) {
1✔
393
                return sd_bus_reply_method_errorf(
×
394
                                m, SD_BUS_ERROR_FAILED, "Subscription '%d' not found", sub_id);
395
        }
396

397
        controller_remove_subscription(controller, sub);
1✔
398
        LIST_REMOVE(subscriptions, monitor->subscriptions, sub);
1✔
399
        subscription_unref(sub);
1✔
400

401
        return sd_bus_reply_method_return(m, "");
1✔
402
}
403

404
/*******************************************************
405
 ********* org.eclipse.bluechi.Monitor.AddPeer *********
406
 *******************************************************/
407

408
static MonitorPeer *monitor_add_peer(Monitor *monitor, const char *peer_name) {
2✔
409
        static uint32_t next_peer_id = 0;
2✔
410

411
        MonitorPeer *peer = malloc0(sizeof(MonitorPeer));
2✔
412
        if (peer == NULL) {
2✔
413
                return NULL;
414
        }
415
        peer->name = strdup(peer_name);
2✔
416
        if (peer->name == NULL) {
2✔
417
                free(peer);
×
418
                return NULL;
×
419
        }
420
        peer->id = ++next_peer_id;
2✔
421

422
        LIST_APPEND(peers, monitor->peers, peer);
2✔
423

424
        bc_log_debugf("Added monitor peer '%s' to monitor '%s'", peer_name, monitor->object_path);
2✔
425
        return peer;
2✔
426
}
427

428
static bool monitor_has_peer_with_name(Monitor *monitor, const char *peer_name) {
3✔
429
        if (streq(monitor->owner, peer_name)) {
3✔
430
                return true;
431
        }
432

433
        MonitorPeer *peer = NULL;
3✔
434
        MonitorPeer *next_peer = NULL;
3✔
435
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
3✔
436
                if (streq(peer->name, peer_name)) {
1✔
437
                        return true;
438
                }
439
        }
440
        bc_log_debugf("Peer with name '%s' for monitor '%s' not found", peer_name, monitor->object_path);
2✔
441

442
        return false;
2✔
443
}
444

445
static int monitor_method_add_peer(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
3✔
446
        Monitor *monitor = userdata;
3✔
447

448
        const char *peer_name = NULL;
3✔
449

450
        int r = sd_bus_message_read(m, "s", &peer_name);
3✔
451
        if (r < 0) {
3✔
452
                return sd_bus_reply_method_errorf(
×
453
                                m,
454
                                SD_BUS_ERROR_INVALID_ARGS,
455
                                "Invalid argument for the peer name: %s",
456
                                strerror(-r));
457
        }
458

459
        if (!bus_id_is_valid(peer_name)) {
3✔
460
                return sd_bus_reply_method_errorf(
×
461
                                m,
462
                                SD_BUS_ERROR_INVALID_ARGS,
463
                                "Peer name '%s' is not a valid bus name",
464
                                peer_name);
465
        }
466

467
        if (monitor_has_peer_with_name(monitor, peer_name)) {
3✔
468
                return sd_bus_reply_method_errorf(
1✔
469
                                m, SD_BUS_ERROR_INVALID_ARGS, "Peer name '%s' has already been added", peer_name);
470
        }
471

472
        MonitorPeer *peer = monitor_add_peer(monitor, peer_name);
2✔
473
        if (peer == NULL) {
2✔
474
                return sd_bus_reply_method_errorf(
×
475
                                m, SD_BUS_ERROR_NO_MEMORY, "Failed to add peer '%s': OOM", peer_name);
476
        }
477

478
        return sd_bus_reply_method_return(m, "u", peer->id);
2✔
479
}
480

481
/*******************************************************
482
 ********* org.eclipse.bluechi.Monitor.RemovePeer *********
483
 *******************************************************/
484

485
static MonitorPeer *monitor_find_peer(Monitor *monitor, uint32_t peer_id) {
×
486
        MonitorPeer *peer = NULL;
×
487
        MonitorPeer *next_peer = NULL;
×
488
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
×
489
                if (peer->id == peer_id) {
×
490
                        return peer;
491
                }
492
        }
493
        bc_log_debugf("Peer with ID '%d' for monitor '%s' not found", peer_id, monitor->object_path);
×
494

495
        return NULL;
×
496
}
497

498
static int monitor_method_remove_peer(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
×
499
        Monitor *monitor = userdata;
×
500

501
        uint32_t peer_id = 0;
×
502
        const char *reason = NULL;
×
503

504
        int r = sd_bus_message_read(m, "us", &peer_id, &reason);
×
505
        if (r < 0) {
×
506
                return sd_bus_reply_method_errorf(
×
507
                                m,
508
                                SD_BUS_ERROR_INVALID_ARGS,
509
                                "Invalid argument for the peer name: %s",
510
                                strerror(-r));
511
        }
512

513
        MonitorPeer *peer = monitor_find_peer(monitor, peer_id);
×
514
        if (peer == NULL) {
×
515
                return sd_bus_reply_method_errorf(
×
516
                                m, SD_BUS_ERROR_FAILED, "Peer with ID '%d' not found.", peer_id);
517
        }
518

519
        monitor_emit_peer_removed(monitor, peer, reason);
×
520
        LIST_REMOVE(peers, monitor->peers, peer);
×
521
        free_and_null(peer->name);
×
522
        free_and_null(peer);
×
523

524
        bc_log_debugf("Removed monitor peer '%d' to monitor '%s'", peer_id, monitor->object_path);
×
525
        return sd_bus_reply_method_return(m, "");
×
526
}
527

528

529
/**********************************
530
 ********* Monitor events *********
531
 **********************************/
532

533
static sd_bus_message *assemble_unit_new_signal(
534
                Monitor *monitor, const char *node, const char *unit, const char *reason);
535
static sd_bus_message *assemble_unit_removed_signal(
536
                Monitor *monitor, const char *node, const char *unit, const char *reason);
537
static sd_bus_message *assemble_unit_property_changed_signal(
538
                Monitor *monitor, const char *node, const char *unit, const char *interface, sd_bus_message *m);
539
static sd_bus_message *assemble_unit_state_changed_signal(
540
                Monitor *monitor,
541
                const char *node,
542
                const char *unit,
543
                const char *active_state,
544
                const char *substate,
545
                const char *reason);
546

547
int monitor_on_unit_property_changed(
94✔
548
                void *userdata, const char *node, const char *unit, const char *interface, sd_bus_message *m) {
549
        Monitor *monitor = (Monitor *) userdata;
94✔
550
        Controller *controller = monitor->controller;
94✔
551

552
        int r = 0;
94✔
553
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
188✔
554

555
        sig = assemble_unit_property_changed_signal(monitor, node, unit, interface, m);
94✔
556
        if (sig != NULL) {
94✔
557
                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
94✔
558
                if (r < 0) {
94✔
559
                        bc_log_errorf("Monitor: %s, failed to send UnitPropertyChanged signal to monitor owner: %s",
×
560
                                      monitor->object_path,
561
                                      strerror(-r));
562
                }
563
                sd_bus_message_unrefp(&sig);
94✔
564
                sig = NULL;
565
        }
566

567
        MonitorPeer *peer = NULL;
94✔
568
        MonitorPeer *next_peer = NULL;
94✔
569
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
94✔
570
                sig = assemble_unit_property_changed_signal(monitor, node, unit, interface, m);
10✔
571
                if (sig != NULL) {
10✔
572
                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
10✔
573
                        if (r < 0) {
10✔
574
                                bc_log_errorf("Monitor: %s, failed to send UnitPropertyChanged signal to peer '%s': %s",
×
575
                                              monitor->object_path,
576
                                              peer->name,
577
                                              strerror(-r));
578
                        }
579
                        sd_bus_message_unrefp(&sig);
114✔
580
                        sig = NULL;
581
                }
582
        }
583

584
        return 0;
94✔
585
}
586

587
int monitor_on_unit_new(void *userdata, const char *node, const char *unit, const char *reason) {
15✔
588
        Monitor *monitor = (Monitor *) userdata;
15✔
589
        Controller *controller = monitor->controller;
15✔
590

591
        int r = 0;
15✔
592
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
30✔
593

594
        sig = assemble_unit_new_signal(monitor, node, unit, reason);
15✔
595
        if (sig != NULL) {
15✔
596
                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
15✔
597
                if (r < 0) {
15✔
598
                        bc_log_errorf("Monitor: %s, failed to send UnitNew signal to monitor owner: %s",
×
599
                                      monitor->object_path,
600
                                      strerror(-r));
601
                }
602
                sd_bus_message_unrefp(&sig);
15✔
603
                sig = NULL;
604
        }
605

606
        MonitorPeer *peer = NULL;
15✔
607
        MonitorPeer *next_peer = NULL;
15✔
608
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
15✔
609
                sig = assemble_unit_new_signal(monitor, node, unit, reason);
1✔
610
                if (sig != NULL) {
1✔
611
                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
1✔
612
                        if (r < 0) {
1✔
613
                                bc_log_errorf("Monitor: %s, failed to send signal to peer '%s': %s",
×
614
                                              monitor->object_path,
615
                                              peer->name,
616
                                              strerror(-r));
617
                        }
618
                        sd_bus_message_unrefp(&sig);
17✔
619
                        sig = NULL;
620
                }
621
        }
622

623
        return 0;
15✔
624
}
625

626
int monitor_on_unit_state_changed(
18✔
627
                void *userdata,
628
                const char *node,
629
                const char *unit,
630
                const char *active_state,
631
                const char *substate,
632
                const char *reason) {
633
        Monitor *monitor = (Monitor *) userdata;
18✔
634
        Controller *controller = monitor->controller;
18✔
635

636
        int r = 0;
18✔
637
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
36✔
638

639
        sig = assemble_unit_state_changed_signal(monitor, node, unit, active_state, substate, reason);
18✔
640
        if (sig != NULL) {
18✔
641
                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
18✔
642
                if (r < 0) {
18✔
643
                        bc_log_errorf("Monitor: %s, failed to send signal to monitor owner: %s",
×
644
                                      monitor->object_path,
645
                                      strerror(-r));
646
                }
647
                sd_bus_message_unrefp(&sig);
18✔
648
                sig = NULL;
649
        }
650

651
        MonitorPeer *peer = NULL;
18✔
652
        MonitorPeer *next_peer = NULL;
18✔
653
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
18✔
654
                sig = assemble_unit_state_changed_signal(monitor, node, unit, active_state, substate, reason);
2✔
655
                if (sig != NULL) {
2✔
656
                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
2✔
657
                        if (r < 0) {
2✔
658
                                bc_log_errorf("Monitor: %s, failed to send UnitStateChanged signal to peer '%s': %s",
×
659
                                              monitor->object_path,
660
                                              peer->name,
661
                                              strerror(-r));
662
                        }
663
                        sd_bus_message_unrefp(&sig);
22✔
664
                        sig = NULL;
665
                }
666
        }
667

668
        return 0;
18✔
669
}
670

671
int monitor_on_unit_removed(void *userdata, const char *node, const char *unit, const char *reason) {
9✔
672
        Monitor *monitor = (Monitor *) userdata;
9✔
673
        Controller *controller = monitor->controller;
9✔
674

675
        int r = 0;
9✔
676
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
18✔
677

678
        sig = assemble_unit_removed_signal(monitor, node, unit, reason);
9✔
679
        if (sig != NULL) {
9✔
680
                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
9✔
681
                if (r < 0) {
9✔
682
                        bc_log_errorf("Monitor: %s, failed to send signal to monitor owner: %s",
×
683
                                      monitor->object_path,
684
                                      strerror(-r));
685
                }
686
                sd_bus_message_unrefp(&sig);
9✔
687
                sig = NULL;
688
        }
689

690
        MonitorPeer *peer = NULL;
9✔
691
        MonitorPeer *next_peer = NULL;
9✔
692
        LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
9✔
693
                sig = assemble_unit_removed_signal(monitor, node, unit, reason);
1✔
694
                if (sig != NULL) {
1✔
695
                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
1✔
696
                        if (r < 0) {
1✔
697
                                bc_log_errorf("Monitor: %s, failed to send UnitRemoved signal to peer '%s': %s",
×
698
                                              monitor->object_path,
699
                                              peer->name,
700
                                              strerror(-r));
701
                        }
702
                        sd_bus_message_unrefp(&sig);
11✔
703
                        sig = NULL;
704
                }
705
        }
706

707
        return 0;
9✔
708
}
709

710

711
static sd_bus_message *assemble_unit_new_signal(
16✔
712
                Monitor *monitor, const char *node, const char *unit, const char *reason) {
713
        Controller *controller = monitor->controller;
16✔
714

715
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
16✔
716
        int r = sd_bus_message_new_signal(
32✔
717
                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitNew");
16✔
718
        if (r < 0) {
16✔
719
                bc_log_errorf("Monitor: %s, failed to create UnitNew signal: %s",
×
720
                              monitor->object_path,
721
                              strerror(-r));
722
                return NULL;
723
        }
724

725
        r = sd_bus_message_append(sig, "sss", node, unit, reason);
16✔
726
        if (r < 0) {
16✔
727
                bc_log_errorf("Monitor: %s, failed to append data to UnitNew signal: %s",
×
728
                              monitor->object_path,
729
                              strerror(-r));
730
                return NULL;
731
        }
732

733
        return steal_pointer(&sig);
16✔
734
}
735

736
static sd_bus_message *assemble_unit_removed_signal(
10✔
737
                Monitor *monitor, const char *node, const char *unit, const char *reason) {
738
        Controller *controller = monitor->controller;
10✔
739

740
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
10✔
741
        int r = sd_bus_message_new_signal(
20✔
742
                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitRemoved");
10✔
743
        if (r < 0) {
10✔
744
                bc_log_errorf("Monitor: %s, failed to create UnitRemoved signal: %s",
×
745
                              monitor->object_path,
746
                              strerror(-r));
747
                return NULL;
748
        }
749

750
        r = sd_bus_message_append(sig, "sss", node, unit, reason);
10✔
751
        if (r < 0) {
10✔
752
                bc_log_errorf("Monitor: %s, failed to append data to UnitRemoved signal: %s",
×
753
                              monitor->object_path,
754
                              strerror(-r));
755
                return NULL;
756
        }
757

758
        return steal_pointer(&sig);
10✔
759
}
760

761
static sd_bus_message *assemble_unit_property_changed_signal(
104✔
762
                Monitor *monitor, const char *node, const char *unit, const char *interface, sd_bus_message *m) {
763
        Controller *controller = monitor->controller;
104✔
764

765
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
104✔
766
        int r = sd_bus_message_new_signal(
208✔
767
                        controller->api_bus,
768
                        &sig,
769
                        monitor->object_path,
104✔
770
                        MONITOR_INTERFACE,
771
                        "UnitPropertiesChanged");
772
        if (r < 0) {
104✔
773
                bc_log_errorf("Monitor: %s, failed to create UnitPropertiesChanged signal: %s",
×
774
                              monitor->object_path,
775
                              strerror(-r));
776
                return NULL;
777
        }
778

779
        r = sd_bus_message_append(sig, "sss", node, unit, interface);
104✔
780
        if (r < 0) {
104✔
781
                bc_log_errorf("Monitor: %s, failed to append data to UnitPropertiesChanged signal: %s",
×
782
                              monitor->object_path,
783
                              strerror(-r));
784
                return NULL;
785
        }
786

787
        r = sd_bus_message_skip(m, "ss"); // Skip unit & iface
104✔
788
        if (r < 0) {
104✔
789
                bc_log_errorf("Monitor: %s, failed to skip unit and interface for UnitPropertiesChanged signal: %s",
×
790
                              monitor->object_path,
791
                              strerror(-r));
792
                return NULL;
793
        }
794

795
        r = sd_bus_message_copy(sig, m, false);
104✔
796
        if (r < 0) {
104✔
797
                bc_log_errorf("Monitor: %s, failed to copy properties for UnitPropertiesChanged signal: %s",
×
798
                              monitor->object_path,
799
                              strerror(-r));
800
                return NULL;
801
        }
802

803
        r = sd_bus_message_rewind(m, false);
104✔
804
        if (r < 0) {
104✔
805
                bc_log_errorf("Monitor: %s, failed to rewind original UnitPropertiesChanged signal: %s",
×
806
                              monitor->object_path,
807
                              strerror(-r));
808
                return NULL;
809
        }
810

811
        return steal_pointer(&sig);
104✔
812
}
813

814
static sd_bus_message *assemble_unit_state_changed_signal(
20✔
815
                Monitor *monitor,
816
                const char *node,
817
                const char *unit,
818
                const char *active_state,
819
                const char *substate,
820
                const char *reason) {
821
        Controller *controller = monitor->controller;
20✔
822

823
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
20✔
824
        int r = sd_bus_message_new_signal(
40✔
825
                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitStateChanged");
20✔
826
        if (r < 0) {
20✔
827
                bc_log_errorf("Monitor: %s, failed to create UnitStateChanged signal: %s",
×
828
                              monitor->object_path,
829
                              strerror(-r));
830
                return NULL;
831
        }
832

833
        r = sd_bus_message_append(sig, "sssss", node, unit, active_state, substate, reason);
20✔
834
        if (r < 0) {
20✔
835
                bc_log_errorf("Monitor: %s, failed to append data to UnitStateChanged signal: %s",
×
836
                              monitor->object_path,
837
                              strerror(-r));
838
                return NULL;
839
        }
840

841
        return steal_pointer(&sig);
20✔
842
}
843

844
static void monitor_emit_peer_removed(void *userdata, MonitorPeer *peer, const char *reason) {
2✔
845
        Monitor *monitor = (Monitor *) userdata;
2✔
846
        Controller *controller = monitor->controller;
2✔
847

848
        _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
2✔
849
        int r = sd_bus_message_new_signal(
4✔
850
                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "PeerRemoved");
2✔
851
        if (r < 0) {
2✔
852
                bc_log_errorf("Monitor: %s, failed to create PeerRemoved signal: %s",
×
853
                              monitor->object_path,
854
                              strerror(-r));
855
                return;
856
        }
857

858
        r = sd_bus_message_append(sig, "s", reason);
2✔
859
        if (r < 0) {
2✔
860
                bc_log_errorf("Monitor: %s, failed to append data to PeerRemoved signal: %s",
×
861
                              monitor->object_path,
862
                              strerror(-r));
863
                return;
864
        }
865

866
        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
2✔
867
        if (r < 0) {
2✔
868
                bc_log_errorf("Monitor: %s, failed to send PeerRemoved signal: %s",
×
869
                              monitor->object_path,
870
                              strerror(-r));
871
                return;
872
        }
873
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc