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