]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/async.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
12 #include "process-util.h"
13 #include "signal-util.h"
16 int asynchronous_job(void* (*func
)(void *p
), void *arg
) {
17 sigset_t ss
, saved_ss
;
22 /* It kinda sucks that we have to resort to threads to implement an asynchronous close(), but well, such is
25 r
= pthread_attr_init(&a
);
29 r
= pthread_attr_setdetachstate(&a
, PTHREAD_CREATE_DETACHED
);
35 if (sigfillset(&ss
) < 0) {
40 /* Block all signals before forking off the thread, so that the new thread is started with all signals
41 * blocked. This way the existence of the new thread won't affect signal handling in other threads. */
43 r
= pthread_sigmask(SIG_BLOCK
, &ss
, &saved_ss
);
49 r
= pthread_create(&t
, &a
, func
, arg
);
51 k
= pthread_sigmask(SIG_SETMASK
, &saved_ss
, NULL
);
61 pthread_attr_destroy(&a
);
65 int asynchronous_sync(pid_t
*ret_pid
) {
68 /* This forks off an invocation of fork() as a child process, in order to initiate synchronization to
69 * disk. Note that we implement this as helper process rather than thread as we don't want the sync() to hang our
70 * original process ever, and a thread would do that as the process can't exit with threads hanging in blocking
73 r
= safe_fork("(sd-sync)", FORK_RESET_SIGNALS
|FORK_CLOSE_ALL_FDS
, ret_pid
);
85 static void *close_thread(void *p
) {
86 (void) pthread_setname_np(pthread_self(), "close");
88 assert_se(close_nointr(PTR_TO_FD(p
)) != -EBADF
);
92 int asynchronous_close(int fd
) {
95 /* This is supposed to behave similar to safe_close(), but
96 * actually invoke close() asynchronously, so that it will
97 * never block. Ideally the kernel would have an API for this,
98 * but it doesn't, so we work around it, and hide this as a
99 * far away as we can. */
104 r
= asynchronous_job(close_thread
, FD_TO_PTR(fd
));
106 assert_se(close_nointr(fd
) != -EBADF
);