Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 111

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - 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     |   50 ++++++++++++++++++++++++++++++++++++-------------
 daemon/direct.c        |    7 +++---
 daemon/indirect.c      |    7 +++---
 daemon/state.c         |    7 +++---
 include/master.h       |    3 ++
 lib/master.c           |   36 +++++++++++++++++++++++++++++++----
 modules/mount_autofs.c |    4 +--
 7 files changed, 86 insertions(+), 28 deletions(-)


--- autofs-5.0.1.orig/daemon/automount.c
+++ autofs-5.0.1/daemon/automount.c
@@ -64,8 +64,9 @@ static int st_stat = 0;
 static int *pst_stat = &st_stat;
 static pthread_t state_mach_thid;
 
-/* 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};
@@ -1212,7 +1213,7 @@ static pthread_t do_signals(struct maste
 	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");
@@ -1301,7 +1302,7 @@ static int do_hup_signal(struct master *
 
 	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");
@@ -1347,8 +1348,22 @@ static void *statemachine(void *arg)
 		case SIGTERM:
 		case SIGINT:
 		case SIGUSR2:
-			if (master_list_empty(master_list))
-				return NULL;
+			master_mutex_lock();
+			if (list_empty(&master_list->completed)) {
+				if (list_empty(&master_list->mounts)) {
+					master_mutex_unlock();
+					return NULL;
+				}
+			} else {
+				if (master_done(master_list)) {
+					master_mutex_unlock();
+					return NULL;
+				}
+				master_mutex_unlock();
+				break;
+			}
+			master_mutex_unlock();
+
 		case SIGUSR1:
 			do_signals(master_list, sig);
 			break;
@@ -1467,8 +1482,6 @@ static void handle_mounts_cleanup(void *
 	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) {
@@ -1480,8 +1493,12 @@ static void handle_mounts_cleanup(void *
 
 	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;
@@ -2040,7 +2057,14 @@ 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]);
+		exit(1);
+	}
+
+	if (pthread_attr_init(&th_attr_detached)) {
 		logerr("%s: failed to init thread attribute struct!",
 		     program);
 		close(start_pipefd[1]);
@@ -2048,7 +2072,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]);
@@ -2057,7 +2081,7 @@ int main(int argc, char *argv[])
 
 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
 	if (pthread_attr_setstacksize(
-			&thread_attr, PTHREAD_STACK_MIN*128)) {
+			&th_attr_detached, PTHREAD_STACK_MIN*128)) {
 		logerr("%s: failed to set stack size thread attribute!",
 		     program);
 		close(start_pipefd[1]);
--- autofs-5.0.1.orig/daemon/direct.c
+++ autofs-5.0.1/daemon/direct.c
@@ -38,7 +38,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;
@@ -1177,7 +1178,7 @@ int handle_packet_expire_direct(struct a
 	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");
 		send_fail(ap->logopt, mt->ioctlfd, pkt->wait_queue_token);
@@ -1459,7 +1460,7 @@ int handle_packet_missing_direct(struct 
 	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");
 		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
--- autofs-5.0.1.orig/daemon/indirect.c
+++ autofs-5.0.1/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;
 
@@ -669,7 +670,7 @@ int handle_packet_expire_indirect(struct
 	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");
 		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
@@ -838,7 +839,7 @@ int handle_packet_missing_indirect(struc
 	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");
 		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
--- autofs-5.0.1.orig/daemon/state.c
+++ autofs-5.0.1/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 au
 	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 au
 	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);
--- autofs-5.0.1.orig/include/master.h
+++ autofs-5.0.1/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 m
 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
--- autofs-5.0.1.orig/lib/master.c
+++ autofs-5.0.1/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;
 
@@ -703,11 +703,16 @@ void master_add_mapent(struct master *ma
 
 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;
 }
 
@@ -785,6 +790,7 @@ struct master *master_new(const char *na
 	master->logopt = master->default_logging;
 
 	INIT_LIST_HEAD(&master->mounts);
+	INIT_LIST_HEAD(&master->completed);
 
 	return master;
 }
@@ -992,7 +998,7 @@ static int master_do_mount(struct master
 
 	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",
@@ -1169,6 +1175,28 @@ int master_list_empty(struct master *mas
 	return res;
 }
 
+int master_done(struct master *master)
+{
+	struct list_head *head, *p;
+	struct master_mapent *entry;
+	int res = 0;
+
+	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;
+
+	return res;
+}
+
 inline unsigned int master_get_logopt(void)
 {
 	return master_list ? master_list->logopt : LOGOPT_NONE;
--- autofs-5.0.1.orig/modules/mount_autofs.c
+++ autofs-5.0.1/modules/mount_autofs.c
@@ -32,7 +32,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 */
@@ -232,7 +232,7 @@ int mount_mount(struct autofs_point *ap,
 	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",