]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-async.c
presets: Don't enable systemd-homed-firstboot.service by default
[thirdparty/systemd.git] / src / test / test-async.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <fcntl.h>
4 #include <sys/prctl.h>
5 #include <sys/wait.h>
6 #include <unistd.h>
7
8 #include "async.h"
9 #include "fs-util.h"
10 #include "path-util.h"
11 #include "process-util.h"
12 #include "signal-util.h"
13 #include "time-util.h"
14 #include "tests.h"
15 #include "tmpfile-util.h"
16
17 TEST(asynchronous_sync) {
18 ASSERT_OK(asynchronous_sync(NULL));
19 }
20
21 static void wait_fd_closed(int fd) {
22 for (unsigned trial = 0; trial < 100; trial++) {
23 usleep_safe(100 * USEC_PER_MSEC);
24 if (fcntl(fd, F_GETFD) < 0) {
25 assert_se(errno == EBADF);
26 return;
27 }
28 }
29
30 assert_not_reached();
31 }
32
33 TEST(asynchronous_close) {
34 _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-asynchronous_close.XXXXXX";
35 int fd, r;
36
37 fd = mkostemp_safe(name);
38 ASSERT_OK(fd);
39 asynchronous_close(fd);
40 wait_fd_closed(fd);
41
42 r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
43 ASSERT_OK(r);
44
45 if (r == 0) {
46 /* child */
47
48 ASSERT_OK(make_reaper_process(true));
49
50 fd = open("/dev/null", O_RDONLY|O_CLOEXEC);
51 ASSERT_OK(fd);
52 asynchronous_close(fd);
53 wait_fd_closed(fd);
54
55 _exit(EXIT_SUCCESS);
56 }
57 }
58
59 static void wait_rm_rf(const char *path) {
60 for (unsigned trial = 0; trial < 100; trial++) {
61 usleep_safe(100 * USEC_PER_MSEC);
62 if (access(path, F_OK) < 0) {
63 assert_se(errno == ENOENT);
64 return;
65 }
66 }
67
68 assert_not_reached();
69 }
70
71 TEST(asynchronous_rm_rf) {
72 _cleanup_free_ char *t = NULL, *k = NULL;
73 int r;
74
75 ASSERT_OK(mkdtemp_malloc(NULL, &t));
76 assert_se(k = path_join(t, "somefile"));
77 ASSERT_OK(touch(k));
78 ASSERT_OK(asynchronous_rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL));
79 wait_rm_rf(t);
80
81 /* Do this once more, from a subreaper. Which is nice, because we can watch the async child even
82 * though detached */
83
84 r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
85 ASSERT_OK(r);
86
87 if (r == 0) {
88 _cleanup_free_ char *tt = NULL, *kk = NULL;
89
90 /* child */
91
92 ASSERT_OK(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD));
93 ASSERT_OK(make_reaper_process(true));
94
95 ASSERT_OK(mkdtemp_malloc(NULL, &tt));
96 assert_se(kk = path_join(tt, "somefile"));
97 ASSERT_OK(touch(kk));
98 ASSERT_OK(asynchronous_rm_rf(tt, REMOVE_ROOT|REMOVE_PHYSICAL));
99
100 for (;;) {
101 siginfo_t si = {};
102
103 ASSERT_OK(waitid(P_ALL, 0, &si, WEXITED));
104
105 if (access(tt, F_OK) < 0) {
106 assert_se(errno == ENOENT);
107 break;
108 }
109
110 /* wasn't the rm_rf() call. let's wait longer */
111 }
112
113 _exit(EXIT_SUCCESS);
114 }
115 }
116
117
118 DEFINE_TEST_MAIN(LOG_DEBUG);