]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-chat.c
core: fix return value in error path after sd_event_add_io() failure
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-chat.c
CommitLineData
89ffcd2a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <assert.h>
23#include <stdlib.h>
24#include <pthread.h>
e3017af9 25#include <unistd.h>
2c93b4ef 26#include <fcntl.h>
89ffcd2a
LP
27
28#include "log.h"
29#include "util.h"
49e5de64 30#include "macro.h"
89ffcd2a
LP
31
32#include "sd-bus.h"
33#include "bus-message.h"
e3017af9 34#include "bus-error.h"
392d5b37
LP
35#include "bus-match.h"
36#include "bus-internal.h"
40ca29a1 37#include "bus-util.h"
392d5b37 38
ebcf1f97 39static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
392d5b37
LP
40 log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
41 return 0;
42}
89ffcd2a 43
ebcf1f97 44static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
a652755d
LP
45 int r;
46
47 assert(bus);
48
eb01ba5d 49 if (sd_bus_message_is_method_error(m, NULL))
a652755d
LP
50 return 0;
51
52 if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
a652755d
LP
53 log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
54
df2d202e 55 r = sd_bus_reply_method_return(m, NULL);
f647962d
MS
56 if (r < 0)
57 return log_error_errno(r, "Failed to send reply: %m");
a652755d
LP
58
59 return 1;
60 }
61
62 return 0;
63}
64
89ffcd2a
LP
65static int server_init(sd_bus **_bus) {
66 sd_bus *bus = NULL;
d728d708 67 sd_id128_t id;
89ffcd2a 68 int r;
20902f3e 69 const char *unique;
89ffcd2a
LP
70
71 assert(_bus);
72
73 r = sd_bus_open_user(&bus);
74 if (r < 0) {
da927ba9 75 log_error_errno(r, "Failed to connect to user bus: %m");
89ffcd2a
LP
76 goto fail;
77 }
78
f7fce345 79 r = sd_bus_get_owner_id(bus, &id);
d728d708 80 if (r < 0) {
da927ba9 81 log_error_errno(r, "Failed to get server ID: %m");
d728d708
LP
82 goto fail;
83 }
84
20902f3e
LP
85 r = sd_bus_get_unique_name(bus, &unique);
86 if (r < 0) {
da927ba9 87 log_error_errno(r, "Failed to get unique name: %m");
20902f3e
LP
88 goto fail;
89 }
90
d728d708 91 log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
20902f3e 92 log_info("Unique ID: %s", unique);
d728d708 93 log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
d728d708 94
89ffcd2a
LP
95 r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
96 if (r < 0) {
da927ba9 97 log_error_errno(r, "Failed to acquire name: %m");
89ffcd2a
LP
98 goto fail;
99 }
100
19befb2d 101 r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
a652755d 102 if (r < 0) {
da927ba9 103 log_error_errno(r, "Failed to add object: %m");
a652755d
LP
104 goto fail;
105 }
106
19befb2d 107 r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
392d5b37 108 if (r < 0) {
da927ba9 109 log_error_errno(r, "Failed to add match: %m");
392d5b37
LP
110 goto fail;
111 }
112
19befb2d 113 r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
392d5b37 114 if (r < 0) {
da927ba9 115 log_error_errno(r, "Failed to add match: %m");
392d5b37
LP
116 goto fail;
117 }
118
119 bus_match_dump(&bus->match_callbacks, 0);
120
89ffcd2a
LP
121 *_bus = bus;
122 return 0;
123
124fail:
125 if (bus)
126 sd_bus_unref(bus);
127
128 return r;
129}
130
e3017af9 131static int server(sd_bus *bus) {
89ffcd2a 132 int r;
e3017af9 133 bool client1_gone = false, client2_gone = false;
89ffcd2a 134
e3017af9 135 while (!client1_gone || !client2_gone) {
d4100e24 136 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2571ead1 137 pid_t pid = 0;
4a875b61 138 const char *label = NULL;
89ffcd2a
LP
139
140 r = sd_bus_process(bus, &m);
141 if (r < 0) {
da927ba9 142 log_error_errno(r, "Failed to process requests: %m");
89ffcd2a
LP
143 goto fail;
144 }
e3017af9 145
89ffcd2a
LP
146 if (r == 0) {
147 r = sd_bus_wait(bus, (uint64_t) -1);
148 if (r < 0) {
da927ba9 149 log_error_errno(r, "Failed to wait: %m");
89ffcd2a
LP
150 goto fail;
151 }
152
153 continue;
154 }
155
e3017af9
LP
156 if (!m)
157 continue;
158
5b12334d
LP
159 sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
160 sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
de0671ee 161 log_info("Got message! member=%s pid="PID_FMT" label=%s",
4a875b61 162 strna(sd_bus_message_get_member(m)),
de0671ee 163 pid,
4a875b61 164 strna(label));
89ffcd2a
LP
165 /* bus_message_dump(m); */
166 /* sd_bus_message_rewind(m, true); */
167
168 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
169 const char *hello;
170 _cleanup_free_ char *lowercase = NULL;
171
172 r = sd_bus_message_read(m, "s", &hello);
173 if (r < 0) {
da927ba9 174 log_error_errno(r, "Failed to get parameter: %m");
89ffcd2a
LP
175 goto fail;
176 }
177
89ffcd2a
LP
178 lowercase = strdup(hello);
179 if (!lowercase) {
180 r = log_oom();
181 goto fail;
182 }
183
184 ascii_strlower(lowercase);
185
df2d202e 186 r = sd_bus_reply_method_return(m, "s", lowercase);
89ffcd2a 187 if (r < 0) {
da927ba9 188 log_error_errno(r, "Failed to send reply: %m");
89ffcd2a
LP
189 goto fail;
190 }
e3017af9
LP
191 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
192
df2d202e 193 r = sd_bus_reply_method_return(m, NULL);
e3017af9 194 if (r < 0) {
da927ba9 195 log_error_errno(r, "Failed to send reply: %m");
e3017af9
LP
196 goto fail;
197 }
198
199 client1_gone = true;
200 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
201
df2d202e 202 r = sd_bus_reply_method_return(m, NULL);
e3017af9 203 if (r < 0) {
da927ba9 204 log_error_errno(r, "Failed to send reply: %m");
e3017af9
LP
205 goto fail;
206 }
207
208 client2_gone = true;
209 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
210
b7f247e0
LP
211 sleep(1);
212
df2d202e 213 r = sd_bus_reply_method_return(m, NULL);
e3017af9 214 if (r < 0) {
da927ba9 215 log_error_errno(r, "Failed to send reply: %m");
e3017af9
LP
216 goto fail;
217 }
218
2c93b4ef
LP
219 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
220 int fd;
221 static const char x = 'X';
222
223 r = sd_bus_message_read(m, "h", &fd);
224 if (r < 0) {
da927ba9 225 log_error_errno(r, "Failed to get parameter: %m");
2c93b4ef
LP
226 goto fail;
227 }
228
5a330cda
ZJS
229 log_info("Received fd=%d", fd);
230
2c93b4ef
LP
231 if (write(fd, &x, 1) < 0) {
232 log_error("Failed to write to fd: %m");
03e334a1 233 safe_close(fd);
2c93b4ef
LP
234 goto fail;
235 }
236
df2d202e 237 r = sd_bus_reply_method_return(m, NULL);
2c93b4ef 238 if (r < 0) {
da927ba9 239 log_error_errno(r, "Failed to send reply: %m");
2c93b4ef
LP
240 goto fail;
241 }
242
e3017af9 243 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
89ffcd2a 244
d4100e24 245 r = sd_bus_reply_method_error(
df2d202e 246 m,
14c24659 247 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
89ffcd2a 248 if (r < 0) {
da927ba9 249 log_error_errno(r, "Failed to send reply: %m");
89ffcd2a
LP
250 goto fail;
251 }
252 }
253 }
254
255 r = 0;
256
257fail:
e3017af9
LP
258 if (bus) {
259 sd_bus_flush(bus);
89ffcd2a 260 sd_bus_unref(bus);
e3017af9 261 }
89ffcd2a 262
e3017af9 263 return r;
89ffcd2a
LP
264}
265
e3017af9 266static void* client1(void*p) {
e9b807c1 267 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
89ffcd2a 268 sd_bus *bus = NULL;
c784c5ce 269 sd_bus_error error = SD_BUS_ERROR_NULL;
89ffcd2a
LP
270 const char *hello;
271 int r;
2c93b4ef
LP
272 int pp[2] = { -1, -1 };
273 char x;
89ffcd2a
LP
274
275 r = sd_bus_open_user(&bus);
276 if (r < 0) {
da927ba9 277 log_error_errno(r, "Failed to connect to user bus: %m");
89ffcd2a
LP
278 goto finish;
279 }
280
d4100e24 281 r = sd_bus_call_method(
89ffcd2a
LP
282 bus,
283 "org.freedesktop.systemd.test",
284 "/",
285 "org.freedesktop.systemd.test",
286 "LowerCase",
d4100e24
LP
287 &error,
288 &reply,
289 "s",
290 "HELLO");
89ffcd2a 291 if (r < 0) {
da927ba9 292 log_error_errno(r, "Failed to issue method call: %m");
89ffcd2a
LP
293 goto finish;
294 }
295
296 r = sd_bus_message_read(reply, "s", &hello);
297 if (r < 0) {
da927ba9 298 log_error_errno(r, "Failed to get string: %m");
89ffcd2a
LP
299 goto finish;
300 }
301
302 assert(streq(hello, "hello"));
303
2c93b4ef
LP
304 if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
305 log_error("Failed to allocate pipe: %m");
306 r = -errno;
307 goto finish;
308 }
309
5a330cda
ZJS
310 log_info("Sending fd=%d", pp[1]);
311
b7f247e0 312 r = sd_bus_call_method(
2c93b4ef
LP
313 bus,
314 "org.freedesktop.systemd.test",
315 "/",
316 "org.freedesktop.systemd.test",
317 "FileDescriptor",
b7f247e0
LP
318 &error,
319 NULL,
320 "h",
321 pp[1]);
2c93b4ef 322 if (r < 0) {
da927ba9 323 log_error_errno(r, "Failed to issue method call: %m");
2c93b4ef
LP
324 goto finish;
325 }
326
327 errno = 0;
328 if (read(pp[0], &x, 1) <= 0) {
329 log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
330 goto finish;
331 }
332
89ffcd2a
LP
333 r = 0;
334
335finish:
336 if (bus) {
337 _cleanup_bus_message_unref_ sd_bus_message *q;
338
339 r = sd_bus_message_new_method_call(
340 bus,
151b9b96 341 &q,
89ffcd2a
LP
342 "org.freedesktop.systemd.test",
343 "/",
344 "org.freedesktop.systemd.test",
151b9b96 345 "ExitClient1");
b7f247e0 346 if (r < 0)
da927ba9 347 log_error_errno(r, "Failed to allocate method call: %m");
b7f247e0
LP
348 else
349 sd_bus_send(bus, q, NULL);
89ffcd2a 350
89ffcd2a
LP
351 sd_bus_flush(bus);
352 sd_bus_unref(bus);
353 }
354
355 sd_bus_error_free(&error);
2c93b4ef 356
3d94f76c 357 safe_close_pair(pp);
2c93b4ef 358
e3017af9
LP
359 return INT_TO_PTR(r);
360}
361
ebcf1f97 362static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
e3017af9
LP
363 bool *x = userdata;
364
40ca29a1 365 log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
e3017af9
LP
366
367 *x = 1;
368 return 1;
369}
370
371static void* client2(void*p) {
372 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
373 sd_bus *bus = NULL;
c784c5ce 374 sd_bus_error error = SD_BUS_ERROR_NULL;
e3017af9 375 bool quit = false;
b9bf7e2b
LP
376 const char *mid;
377 int r;
e3017af9
LP
378
379 r = sd_bus_open_user(&bus);
380 if (r < 0) {
da927ba9 381 log_error_errno(r, "Failed to connect to user bus: %m");
e3017af9
LP
382 goto finish;
383 }
384
a652755d
LP
385 r = sd_bus_message_new_method_call(
386 bus,
151b9b96 387 &m,
a652755d
LP
388 "org.freedesktop.systemd.test",
389 "/foo/bar/waldo/piep",
390 "org.object.test",
151b9b96 391 "Foobar");
a652755d 392 if (r < 0) {
da927ba9 393 log_error_errno(r, "Failed to allocate method call: %m");
a652755d
LP
394 goto finish;
395 }
396
397 r = sd_bus_send(bus, m, NULL);
398 if (r < 0) {
399 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
400 goto finish;
401 }
402
403 sd_bus_message_unref(m);
404 m = NULL;
405
392d5b37
LP
406 r = sd_bus_message_new_signal(
407 bus,
151b9b96 408 &m,
392d5b37
LP
409 "/foobar",
410 "foo.bar",
151b9b96 411 "Notify");
392d5b37 412 if (r < 0) {
da927ba9 413 log_error_errno(r, "Failed to allocate signal: %m");
392d5b37
LP
414 goto finish;
415 }
416
417 r = sd_bus_send(bus, m, NULL);
418 if (r < 0) {
419 log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
420 goto finish;
421 }
422
423 sd_bus_message_unref(m);
424 m = NULL;
425
b9bf7e2b
LP
426 r = sd_bus_message_new_method_call(
427 bus,
151b9b96 428 &m,
b9bf7e2b
LP
429 "org.freedesktop.systemd.test",
430 "/",
431 "org.freedesktop.DBus.Peer",
151b9b96 432 "GetMachineId");
b9bf7e2b 433 if (r < 0) {
da927ba9 434 log_error_errno(r, "Failed to allocate method call: %m");
b9bf7e2b
LP
435 goto finish;
436 }
437
c49b30a2 438 r = sd_bus_call(bus, m, 0, &error, &reply);
b9bf7e2b
LP
439 if (r < 0) {
440 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
441 goto finish;
442 }
443
444 r = sd_bus_message_read(reply, "s", &mid);
445 if (r < 0) {
da927ba9 446 log_error_errno(r, "Failed to parse machine ID: %m");
b9bf7e2b
LP
447 goto finish;
448 }
449
450 log_info("Machine ID is %s.", mid);
451
452 sd_bus_message_unref(m);
453 m = NULL;
454
e3017af9
LP
455 r = sd_bus_message_new_method_call(
456 bus,
151b9b96 457 &m,
e3017af9
LP
458 "org.freedesktop.systemd.test",
459 "/",
460 "org.freedesktop.systemd.test",
151b9b96 461 "Slow");
e3017af9 462 if (r < 0) {
da927ba9 463 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
464 goto finish;
465 }
466
b9bf7e2b
LP
467 sd_bus_message_unref(reply);
468 reply = NULL;
469
c49b30a2 470 r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
e3017af9
LP
471 if (r < 0)
472 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
473 else
474 log_info("Slow call succeed.");
475
476 sd_bus_message_unref(m);
477 m = NULL;
478
479 r = sd_bus_message_new_method_call(
480 bus,
151b9b96 481 &m,
e3017af9
LP
482 "org.freedesktop.systemd.test",
483 "/",
484 "org.freedesktop.systemd.test",
151b9b96 485 "Slow");
e3017af9 486 if (r < 0) {
da927ba9 487 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
488 goto finish;
489 }
490
19befb2d 491 r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
e3017af9
LP
492 if (r < 0) {
493 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
494 goto finish;
495 }
496
497 while (!quit) {
498 r = sd_bus_process(bus, NULL);
499 if (r < 0) {
da927ba9 500 log_error_errno(r, "Failed to process requests: %m");
e3017af9
LP
501 goto finish;
502 }
503 if (r == 0) {
504 r = sd_bus_wait(bus, (uint64_t) -1);
505 if (r < 0) {
da927ba9 506 log_error_errno(r, "Failed to wait: %m");
e3017af9
LP
507 goto finish;
508 }
509 }
510 }
511
512 r = 0;
513
514finish:
515 if (bus) {
516 _cleanup_bus_message_unref_ sd_bus_message *q;
517
518 r = sd_bus_message_new_method_call(
519 bus,
151b9b96 520 &q,
e3017af9
LP
521 "org.freedesktop.systemd.test",
522 "/",
523 "org.freedesktop.systemd.test",
151b9b96 524 "ExitClient2");
e3017af9 525 if (r < 0) {
da927ba9 526 log_error_errno(r, "Failed to allocate method call: %m");
e3017af9
LP
527 goto finish;
528 }
529
530 sd_bus_send(bus, q, NULL);
531 sd_bus_flush(bus);
532 sd_bus_unref(bus);
533 }
534
535 sd_bus_error_free(&error);
536 return INT_TO_PTR(r);
89ffcd2a
LP
537}
538
539int main(int argc, char *argv[]) {
e3017af9 540 pthread_t c1, c2;
89ffcd2a
LP
541 sd_bus *bus;
542 void *p;
543 int q, r;
544
545 r = server_init(&bus);
49e5de64
ZJS
546 if (r < 0) {
547 log_info("Failed to connect to bus, skipping tests.");
548 return EXIT_TEST_SKIP;
549 }
89ffcd2a 550
e3017af9
LP
551 log_info("Initialized...");
552
553 r = pthread_create(&c1, NULL, client1, bus);
554 if (r != 0)
89ffcd2a 555 return EXIT_FAILURE;
89ffcd2a 556
e3017af9
LP
557 r = pthread_create(&c2, NULL, client2, bus);
558 if (r != 0)
559 return EXIT_FAILURE;
89ffcd2a 560
e3017af9
LP
561 r = server(bus);
562
563 q = pthread_join(c1, &p);
564 if (q != 0)
565 return EXIT_FAILURE;
2181a7f5
LP
566 if (PTR_TO_INT(p) < 0)
567 return EXIT_FAILURE;
568
e3017af9 569 q = pthread_join(c2, &p);
89ffcd2a
LP
570 if (q != 0)
571 return EXIT_FAILURE;
2181a7f5
LP
572 if (PTR_TO_INT(p) < 0)
573 return EXIT_FAILURE;
574
89ffcd2a
LP
575 if (r < 0)
576 return EXIT_FAILURE;
577
578 return EXIT_SUCCESS;
579}