From f485606bf8957d2954cf6fa5b0aabd5c39db15c1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 16 Sep 2013 15:50:38 -0500 Subject: Make tmpdir removal asynchronous https://bugs.freedesktop.org/show_bug.cgi?id=68232 --- src/core/async.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/async.h | 25 +++++++++++++++++++ src/core/execute.c | 41 +++++++++++++++++++------------ src/core/job.c | 2 +- src/core/sync.c | 65 ------------------------------------------------ src/core/sync.h | 24 ------------------ 6 files changed, 123 insertions(+), 106 deletions(-) create mode 100644 src/core/async.c create mode 100644 src/core/async.h delete mode 100644 src/core/sync.c delete mode 100644 src/core/sync.h (limited to 'src/core') diff --git a/src/core/async.c b/src/core/async.c new file mode 100644 index 0000000000..af527bea4e --- /dev/null +++ b/src/core/async.c @@ -0,0 +1,72 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "async.h" +#include "log.h" + +int asynchronous_job(void* (*func)(void *p), void *arg) { + pthread_attr_t a; + pthread_t t; + int r; + + /* 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. */ + + r = pthread_attr_init(&a); + if (r != 0) + return -r; + + r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); + if (r != 0) { + r = -r; + goto finish; + } + + r = pthread_create(&t, &a, func, arg); + if (r != 0) { + r = -r; + goto finish; + } + +finish: + pthread_attr_destroy(&a); + return r; +} + +static void *sync_thread(void *p) { + sync(); + return NULL; +} + +int asynchronous_sync(void) { + log_debug("Spawning new thread for sync"); + + return asynchronous_job(sync_thread, NULL); +} diff --git a/src/core/async.h b/src/core/async.h new file mode 100644 index 0000000000..6601b4dc4b --- /dev/null +++ b/src/core/async.h @@ -0,0 +1,25 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +int asynchronous_job(void* (*func)(void *p), void *arg); +int asynchronous_sync(void); diff --git a/src/core/execute.c b/src/core/execute.c index 43b571e043..f840642d14 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -67,6 +67,7 @@ #include "env-util.h" #include "fileio.h" #include "unit.h" +#include "async.h" #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) @@ -1581,6 +1582,28 @@ void exec_context_init(ExecContext *c) { c->timer_slack_nsec = (nsec_t) -1; } +static void *remove_tmpdir_thread(void *p) { + int r; + _cleanup_free_ char *dirp = p; + char *dir; + + assert(dirp); + + r = rm_rf_dangerous(dirp, false, true, false); + dir = dirname(dirp); + if (r < 0) + log_warning("Failed to remove content of temporary directory %s: %s", + dir, strerror(-r)); + else { + r = rmdir(dir); + if (r < 0) + log_warning("Failed to remove temporary directory %s: %s", + dir, strerror(-r)); + } + + return NULL; +} + void exec_context_tmp_dirs_done(ExecContext *c) { char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir, c->tmp_dir ? c->var_tmp_dir : NULL, @@ -1588,22 +1611,8 @@ void exec_context_tmp_dirs_done(ExecContext *c) { char **dirp; for(dirp = dirs; *dirp; dirp++) { - char *dir; - int r; - - r = rm_rf_dangerous(*dirp, false, true, false); - dir = dirname(*dirp); - if (r < 0) - log_warning("Failed to remove content of temporary directory %s: %s", - dir, strerror(-r)); - else { - r = rmdir(dir); - if (r < 0) - log_warning("Failed to remove temporary directory %s: %s", - dir, strerror(-r)); - } - - free(*dirp); + log_debug("Spawning thread to nuke %s", *dirp); + asynchronous_job(remove_tmpdir_thread, *dirp); } c->tmp_dir = c->var_tmp_dir = NULL; diff --git a/src/core/job.c b/src/core/job.c index 85f77e8f0d..bf1d956908 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -35,7 +35,7 @@ #include "log.h" #include "dbus-job.h" #include "special.h" -#include "sync.h" +#include "async.h" #include "virt.h" JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) { diff --git a/src/core/sync.c b/src/core/sync.c deleted file mode 100644 index 7e74b63071..0000000000 --- a/src/core/sync.c +++ /dev/null @@ -1,65 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "sync.h" - -static void *sync_thread(void *p) { - sync(); - return NULL; -} - -int asynchronous_sync(void) { - pthread_attr_t a; - pthread_t t; - int r; - - /* 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. */ - - r = pthread_attr_init(&a); - if (r != 0) - return -r; - - r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); - if (r != 0) { - r = -r; - goto finish; - } - - r = pthread_create(&t, &a, sync_thread, NULL); - if (r != 0) { - r = -r; - goto finish; - } - -finish: - pthread_attr_destroy(&a); - return r; -} diff --git a/src/core/sync.h b/src/core/sync.h deleted file mode 100644 index eb26c88deb..0000000000 --- a/src/core/sync.h +++ /dev/null @@ -1,24 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -int asynchronous_sync(void); -- cgit v1.2.3-54-g00ecf