]>
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 assert_se(sigfillset(&ss
) >= 0);
37 /* Block all signals before forking off the thread, so that the new thread is started with all signals
38 * blocked. This way the existence of the new thread won't affect signal handling in other threads. */
40 r
= pthread_sigmask(SIG_BLOCK
, &ss
, &saved_ss
);
46 r
= pthread_create(&t
, &a
, func
, arg
);
48 k
= pthread_sigmask(SIG_SETMASK
, &saved_ss
, NULL
);
58 pthread_attr_destroy(&a
);
62 int asynchronous_sync(pid_t
*ret_pid
) {
65 /* This forks off an invocation of fork() as a child process, in order to initiate synchronization to
66 * disk. Note that we implement this as helper process rather than thread as we don't want the sync() to hang our
67 * original process ever, and a thread would do that as the process can't exit with threads hanging in blocking
70 r
= safe_fork("(sd-sync)", FORK_RESET_SIGNALS
|FORK_CLOSE_ALL_FDS
, ret_pid
);
82 static void *close_thread(void *p
) {
83 (void) pthread_setname_np(pthread_self(), "close");
85 assert_se(close_nointr(PTR_TO_FD(p
)) != -EBADF
);
89 int asynchronous_close(int fd
) {
92 /* This is supposed to behave similar to safe_close(), but
93 * actually invoke close() asynchronously, so that it will
94 * never block. Ideally the kernel would have an API for this,
95 * but it doesn't, so we work around it, and hide this as a
96 * far away as we can. */
101 r
= asynchronous_job(close_thread
, FD_TO_PTR(fd
));
103 assert_se(close_nointr(fd
) != -EBADF
);