]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/async.c
smack-util: revise smack-util apis and add read smack attr apis
[thirdparty/systemd.git] / src / basic / async.c
CommitLineData
c65eb836
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 <pthread.h>
23#include <unistd.h>
24
f485606b
ZJS
25#include "async.h"
26#include "log.h"
8a474b0c 27#include "util.h"
c65eb836 28
f485606b 29int asynchronous_job(void* (*func)(void *p), void *arg) {
c65eb836
LP
30 pthread_attr_t a;
31 pthread_t t;
32 int r;
33
34 /* It kinda sucks that we have to resort to threads to
35 * implement an asynchronous sync(), but well, such is
36 * life.
37 *
38 * Note that issuing this command right before exiting a
39 * process will cause the process to wait for the sync() to
40 * complete. This function hence is nicely asynchronous really
41 * only in long running processes. */
42
43 r = pthread_attr_init(&a);
c1d630d5 44 if (r > 0)
c65eb836
LP
45 return -r;
46
47 r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
c1d630d5 48 if (r > 0)
c65eb836 49 goto finish;
c65eb836 50
f485606b 51 r = pthread_create(&t, &a, func, arg);
c65eb836
LP
52
53finish:
54 pthread_attr_destroy(&a);
c1d630d5 55 return -r;
c65eb836 56}
f485606b
ZJS
57
58static void *sync_thread(void *p) {
59 sync();
60 return NULL;
61}
62
63int asynchronous_sync(void) {
64 log_debug("Spawning new thread for sync");
65
66 return asynchronous_job(sync_thread, NULL);
67}
8a474b0c
LP
68
69static void *close_thread(void *p) {
5ed12272 70 assert_se(close_nointr(PTR_TO_INT(p)) != -EBADF);
8a474b0c
LP
71 return NULL;
72}
73
74int asynchronous_close(int fd) {
75 int r;
76
77 /* This is supposed to behave similar to safe_close(), but
78 * actually invoke close() asynchronously, so that it will
79 * never block. Ideally the kernel would have an API for this,
80 * but it doesn't, so we work around it, and hide this as a
81 * far away as we can. */
82
5ed12272
LP
83 if (fd >= 0) {
84 PROTECT_ERRNO;
85
86 r = asynchronous_job(close_thread, INT_TO_PTR(fd));
87 if (r < 0)
88 assert_se(close_nointr(fd) != -EBADF);
89 }
8a474b0c
LP
90
91 return -1;
92}