#include "util.h"
int asynchronous_job(void* (*func)(void *p), void *arg) {
+ sigset_t ss, saved_ss;
pthread_attr_t a;
pthread_t t;
- int r;
+ int r, k;
- /* It kinda sucks that we have to resort to threads to
- * implement an asynchronous sync(), but well, such is
- * life.
- *
- * Note that issuing this command right before exiting a
- * process will cause the process to wait for the sync() to
- * complete. This function hence is nicely asynchronous really
- * only in long running processes. */
+ /* It kinda sucks that we have to resort to threads to implement an asynchronous close(), but well, such is
+ * life. */
r = pthread_attr_init(&a);
if (r > 0)
return -r;
r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
- if (r > 0)
+ if (r > 0) {
+ r = -r;
goto finish;
+ }
+
+ if (sigfillset(&ss) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ /* Block all signals before forking off the thread, so that the new thread is started with all signals
+ * blocked. This way the existence of the new thread won't affect signal handling in other threads. */
+
+ r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
+ if (r > 0) {
+ r = -r;
+ goto finish;
+ }
r = pthread_create(&t, &a, func, arg);
+ k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
+
+ if (r > 0)
+ r = -r;
+ else if (k > 0)
+ r = -k;
+ else
+ r = 0;
+
finish:
pthread_attr_destroy(&a);
- return -r;
+ return r;
}
int asynchronous_sync(pid_t *ret_pid) {
if (wait) /* Without using a thread if waiting. */
journal_file_set_offline_internal(f);
else {
+ sigset_t ss, saved_ss;
+ int k;
+
+ if (sigfillset(&ss) < 0)
+ return -errno;
+
+ r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
+ if (r > 0)
+ return -r;
+
r = pthread_create(&f->offline_thread, NULL, journal_file_set_offline_thread, f);
+
+ k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
if (r > 0) {
f->offline_state = OFFLINE_JOINED;
return -r;
}
+ if (k > 0)
+ return -k;
}
return 0;
static void* thread_worker(void *p) {
sd_resolve *resolve = p;
- sigset_t fullset;
-
- /* No signals in this thread please */
- assert_se(sigfillset(&fullset) == 0);
- assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
/* Assign a pretty name to this thread */
(void) pthread_setname_np(pthread_self(), "sd-resolve");
}
static int start_threads(sd_resolve *resolve, unsigned extra) {
+ sigset_t ss, saved_ss;
unsigned n;
- int r;
+ int r, k;
+
+ if (sigfillset(&ss) < 0)
+ return -errno;
+
+ /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist
+ * with a different mask than a fully blocked one */
+ r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
+ if (r > 0)
+ return -r;
n = resolve->n_outstanding + extra;
n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
while (resolve->n_valid_workers < n) {
r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
- if (r != 0)
- return -r;
+ if (r > 0) {
+ r = -r;
+ goto finish;
+ }
resolve->n_valid_workers++;
}
- return 0;
+ r = 0;
+
+finish:
+ k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
+ if (k > 0 && r >= 0)
+ r = -k;
+
+ return r;
}
static bool resolve_pid_changed(sd_resolve *r) {