- fix uri list locking (again).
- check for stale SASL credentials upon connect fail.
- add "forcestart" and "forcerestart" init script options to allow use of
5.0.3 strartup behavior if required.
- always read entire file map into cache to speed lookups.
- make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit.
- make some easy alloca replacements.
- update to configure libtirpc if present.
- update to provide ipv6 name and address support.
- update to provide ipv6 address parsing.
353 lines
11 KiB
Diff
353 lines
11 KiB
Diff
autofs-5.0.4 - library reload fix update
|
|
|
|
From: Ian Kent <raven@themaw.net>
|
|
|
|
We still have a problem with libxml2 being unloaded before its thread
|
|
specific data destructor is called. This is due to the main thread
|
|
exiting (closing the handle we hold open to prevent this) before all
|
|
the mount handling threads have actually completed. This patch makes
|
|
the mount handling threads joinable (and joins with them as they exit)
|
|
to ensure that the mount handling threads have completed before allowing
|
|
the main thread to complete.
|
|
---
|
|
|
|
daemon/automount.c | 35 +++++++++++++++++++++++------------
|
|
daemon/direct.c | 7 ++++---
|
|
daemon/indirect.c | 7 ++++---
|
|
daemon/state.c | 7 ++++---
|
|
include/master.h | 3 +++
|
|
lib/master.c | 38 ++++++++++++++++++++++++++++++++++----
|
|
modules/mount_autofs.c | 4 ++--
|
|
7 files changed, 74 insertions(+), 27 deletions(-)
|
|
|
|
|
|
diff --git a/daemon/automount.c b/daemon/automount.c
|
|
index e120f50..f04273f 100644
|
|
--- a/daemon/automount.c
|
|
+++ b/daemon/automount.c
|
|
@@ -69,8 +69,9 @@ static size_t kpkt_len;
|
|
/* Does kernel know about SOCK_CLOEXEC and friends */
|
|
static int cloexec_works = 0;
|
|
|
|
-/* Attribute to create detached thread */
|
|
-pthread_attr_t thread_attr;
|
|
+/* Attributes for creating detached and joinable threads */
|
|
+pthread_attr_t th_attr;
|
|
+pthread_attr_t th_attr_detached;
|
|
|
|
struct master_readmap_cond mrc = {
|
|
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
|
|
@@ -1192,7 +1193,7 @@ static pthread_t do_signals(struct master *master, int sig)
|
|
if (status)
|
|
fatal(status);
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_notify_state, &r_sig);
|
|
if (status) {
|
|
error(master->logopt,
|
|
"mount state notify thread create failed");
|
|
@@ -1281,7 +1282,7 @@ static int do_hup_signal(struct master *master, time_t age)
|
|
|
|
master->reading = 1;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_read_master, NULL);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL);
|
|
if (status) {
|
|
error(logopt,
|
|
"master read map thread create failed");
|
|
@@ -1327,7 +1328,7 @@ static void *statemachine(void *arg)
|
|
case SIGTERM:
|
|
case SIGINT:
|
|
case SIGUSR2:
|
|
- if (master_list_empty(master_list))
|
|
+ if (master_done(master_list))
|
|
return NULL;
|
|
case SIGUSR1:
|
|
do_signals(master_list, sig);
|
|
@@ -1448,8 +1449,6 @@ static void handle_mounts_cleanup(void *arg)
|
|
master_mutex_unlock();
|
|
|
|
destroy_logpri_fifo(ap);
|
|
- master_free_mapent_sources(ap->entry, 1);
|
|
- master_free_mapent(ap->entry);
|
|
|
|
if (clean) {
|
|
if (rmdir(path) == -1) {
|
|
@@ -1461,8 +1460,12 @@ static void handle_mounts_cleanup(void *arg)
|
|
|
|
info(logopt, "shut down path %s", path);
|
|
|
|
- /* If we are the last tell the state machine to shutdown */
|
|
- if (!submount && master_list_empty(master_list))
|
|
+ /*
|
|
+ * If we are not a submount send a signal to the signal handler
|
|
+ * so it can join with any completed handle_mounts() threads and
|
|
+ * perform final cleanup.
|
|
+ */
|
|
+ if (!submount)
|
|
pthread_kill(state_mach_thid, SIGTERM);
|
|
|
|
return;
|
|
@@ -1980,7 +1983,15 @@ int main(int argc, char *argv[])
|
|
exit(1);
|
|
}
|
|
|
|
- if (pthread_attr_init(&thread_attr)) {
|
|
+ if (pthread_attr_init(&th_attr)) {
|
|
+ logerr("%s: failed to init thread attribute struct!",
|
|
+ program);
|
|
+ close(start_pipefd[1]);
|
|
+ release_flag_file();
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ if (pthread_attr_init(&th_attr_detached)) {
|
|
logerr("%s: failed to init thread attribute struct!",
|
|
program);
|
|
close(start_pipefd[1]);
|
|
@@ -1989,7 +2000,7 @@ int main(int argc, char *argv[])
|
|
}
|
|
|
|
if (pthread_attr_setdetachstate(
|
|
- &thread_attr, PTHREAD_CREATE_DETACHED)) {
|
|
+ &th_attr_detached, PTHREAD_CREATE_DETACHED)) {
|
|
logerr("%s: failed to set detached thread attribute!",
|
|
program);
|
|
close(start_pipefd[1]);
|
|
@@ -1999,7 +2010,7 @@ int main(int argc, char *argv[])
|
|
|
|
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
|
if (pthread_attr_setstacksize(
|
|
- &thread_attr, PTHREAD_STACK_MIN*64)) {
|
|
+ &th_attr_detached, PTHREAD_STACK_MIN*64)) {
|
|
logerr("%s: failed to set stack size thread attribute!",
|
|
program);
|
|
close(start_pipefd[1]);
|
|
diff --git a/daemon/direct.c b/daemon/direct.c
|
|
index c0243c4..d9dda3d 100644
|
|
--- a/daemon/direct.c
|
|
+++ b/daemon/direct.c
|
|
@@ -37,7 +37,8 @@
|
|
|
|
#include "automount.h"
|
|
|
|
-extern pthread_attr_t thread_attr;
|
|
+/* Attribute to create detached thread */
|
|
+extern pthread_attr_t th_attr_detached;
|
|
|
|
struct mnt_params {
|
|
char *options;
|
|
@@ -1142,7 +1143,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
|
|
debug(ap->logopt, "token %ld, name %s",
|
|
(unsigned long) pkt->wait_queue_token, mt->name);
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_expire_direct, mt);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_expire_direct, mt);
|
|
if (status) {
|
|
error(ap->logopt, "expire thread create failed");
|
|
ops->send_fail(ap->logopt,
|
|
@@ -1451,7 +1452,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
|
|
mt->gid = pkt->gid;
|
|
mt->wait_queue_token = pkt->wait_queue_token;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_mount_direct, mt);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_mount_direct, mt);
|
|
if (status) {
|
|
error(ap->logopt, "missing mount thread create failed");
|
|
ops->send_fail(ap->logopt,
|
|
diff --git a/daemon/indirect.c b/daemon/indirect.c
|
|
index 9d3745c..0721707 100644
|
|
--- a/daemon/indirect.c
|
|
+++ b/daemon/indirect.c
|
|
@@ -36,7 +36,8 @@
|
|
|
|
#include "automount.h"
|
|
|
|
-extern pthread_attr_t thread_attr;
|
|
+/* Attribute to create detached thread */
|
|
+extern pthread_attr_t th_attr_detached;
|
|
|
|
static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
@@ -647,7 +648,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
|
|
mt->len = pkt->len;
|
|
mt->wait_queue_token = pkt->wait_queue_token;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_expire_indirect, mt);
|
|
if (status) {
|
|
error(ap->logopt, "expire thread create failed");
|
|
ops->send_fail(ap->logopt,
|
|
@@ -835,7 +836,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin
|
|
mt->gid = pkt->gid;
|
|
mt->wait_queue_token = pkt->wait_queue_token;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_mount_indirect, mt);
|
|
if (status) {
|
|
error(ap->logopt, "expire thread create failed");
|
|
ops->send_fail(ap->logopt,
|
|
diff --git a/daemon/state.c b/daemon/state.c
|
|
index 87c16a6..cd63be1 100644
|
|
--- a/daemon/state.c
|
|
+++ b/daemon/state.c
|
|
@@ -16,7 +16,8 @@
|
|
|
|
#include "automount.h"
|
|
|
|
-extern pthread_attr_t thread_attr;
|
|
+/* Attribute to create detached thread */
|
|
+extern pthread_attr_t th_attr_detached;
|
|
|
|
struct state_queue {
|
|
pthread_t thid;
|
|
@@ -292,7 +293,7 @@ static enum expire expire_proc(struct autofs_point *ap, int now)
|
|
else
|
|
expire = expire_proc_direct;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, expire, ea);
|
|
+ status = pthread_create(&thid, &th_attr_detached, expire, ea);
|
|
if (status) {
|
|
error(ap->logopt,
|
|
"expire thread create for %s failed", ap->path);
|
|
@@ -519,7 +520,7 @@ static unsigned int st_readmap(struct autofs_point *ap)
|
|
ra->ap = ap;
|
|
ra->now = now;
|
|
|
|
- status = pthread_create(&thid, &thread_attr, do_readmap, ra);
|
|
+ status = pthread_create(&thid, &th_attr_detached, do_readmap, ra);
|
|
if (status) {
|
|
error(ap->logopt, "read map thread create failed");
|
|
st_readmap_cleanup(ra);
|
|
diff --git a/include/master.h b/include/master.h
|
|
index 6d801a9..c519e97 100644
|
|
--- a/include/master.h
|
|
+++ b/include/master.h
|
|
@@ -48,6 +48,7 @@ struct master_mapent {
|
|
struct map_source *maps;
|
|
struct autofs_point *ap;
|
|
struct list_head list;
|
|
+ struct list_head join;
|
|
};
|
|
|
|
struct master {
|
|
@@ -61,6 +62,7 @@ struct master {
|
|
unsigned int logopt;
|
|
struct mapent_cache *nc;
|
|
struct list_head mounts;
|
|
+ struct list_head completed;
|
|
};
|
|
|
|
/* From the yacc master map parser */
|
|
@@ -109,6 +111,7 @@ void master_notify_state_change(struct master *, int);
|
|
int master_mount_mounts(struct master *, time_t, int);
|
|
extern inline unsigned int master_get_logopt(void);
|
|
int master_list_empty(struct master *);
|
|
+int master_done(struct master *);
|
|
int master_kill(struct master *);
|
|
|
|
#endif
|
|
diff --git a/lib/master.c b/lib/master.c
|
|
index e1cc062..762094f 100644
|
|
--- a/lib/master.c
|
|
+++ b/lib/master.c
|
|
@@ -32,8 +32,8 @@ struct master *master_list = NULL;
|
|
|
|
extern long global_negative_timeout;
|
|
|
|
-/* Attribute to create detached thread */
|
|
-extern pthread_attr_t thread_attr;
|
|
+/* Attribute to create a joinable thread */
|
|
+extern pthread_attr_t th_attr;
|
|
|
|
extern struct startup_cond suc;
|
|
|
|
@@ -704,11 +704,16 @@ void master_add_mapent(struct master *master, struct master_mapent *entry)
|
|
|
|
void master_remove_mapent(struct master_mapent *entry)
|
|
{
|
|
+ struct master *master = entry->master;
|
|
+
|
|
if (entry->ap->submount)
|
|
return;
|
|
|
|
- if (!list_empty(&entry->list))
|
|
+ if (!list_empty(&entry->list)) {
|
|
list_del_init(&entry->list);
|
|
+ list_add(&entry->join, &master->completed);
|
|
+ }
|
|
+
|
|
return;
|
|
}
|
|
|
|
@@ -786,6 +791,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g
|
|
master->logopt = master->default_logging;
|
|
|
|
INIT_LIST_HEAD(&master->mounts);
|
|
+ INIT_LIST_HEAD(&master->completed);
|
|
|
|
return master;
|
|
}
|
|
@@ -993,7 +999,7 @@ static int master_do_mount(struct master_mapent *entry)
|
|
|
|
debug(ap->logopt, "mounting %s", entry->path);
|
|
|
|
- status = pthread_create(&thid, &thread_attr, handle_mounts, &suc);
|
|
+ status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
|
|
if (status) {
|
|
crit(ap->logopt,
|
|
"failed to create mount handler thread for %s",
|
|
@@ -1170,6 +1176,30 @@ int master_list_empty(struct master *master)
|
|
return res;
|
|
}
|
|
|
|
+int master_done(struct master *master)
|
|
+{
|
|
+ struct list_head *head, *p;
|
|
+ struct master_mapent *entry;
|
|
+ int res = 0;
|
|
+
|
|
+ master_mutex_lock();
|
|
+ head = &master->completed;
|
|
+ p = head->next;
|
|
+ while (p != head) {
|
|
+ entry = list_entry(p, struct master_mapent, join);
|
|
+ p = p->next;
|
|
+ list_del(&entry->join);
|
|
+ pthread_join(entry->thid, NULL);
|
|
+ master_free_mapent_sources(entry, 1);
|
|
+ master_free_mapent(entry);
|
|
+ }
|
|
+ if (list_empty(&master->mounts))
|
|
+ res = 1;
|
|
+ master_mutex_unlock();
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
inline unsigned int master_get_logopt(void)
|
|
{
|
|
return master_list ? master_list->logopt : LOGOPT_NONE;
|
|
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
|
|
index 82a5ef3..44fc043 100644
|
|
--- a/modules/mount_autofs.c
|
|
+++ b/modules/mount_autofs.c
|
|
@@ -30,7 +30,7 @@
|
|
#define MODPREFIX "mount(autofs): "
|
|
|
|
/* Attribute to create detached thread */
|
|
-extern pthread_attr_t thread_attr;
|
|
+extern pthread_attr_t th_attr_detached;
|
|
extern struct startup_cond suc;
|
|
|
|
int mount_version = AUTOFS_MOUNT_VERSION; /* Required by protocol */
|
|
@@ -235,7 +235,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
|
|
suc.done = 0;
|
|
suc.status = 0;
|
|
|
|
- if (pthread_create(&thid, &thread_attr, handle_mounts, &suc)) {
|
|
+ if (pthread_create(&thid, &th_attr_detached, handle_mounts, &suc)) {
|
|
crit(ap->logopt,
|
|
MODPREFIX
|
|
"failed to create mount handler thread for %s",
|