diff --git a/CHANGELOG b/CHANGELOG
index 78a4cf8..b6e30c4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -33,6 +33,7 @@
 - fix directory cleanup on expire.
 - fix task cancelation at shutdown.
 - fix included map wild card key lookup.
+- fix task cancelation at shutdown (more).
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 8195349..343fd68 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -391,9 +391,12 @@ static int umount_subtree_mounts(struct 
 
 	left = 0;
 
+	pthread_cleanup_push(cache_lock_cleanup, mc);
+
 	if (me->multi) {
 		char *root, *base;
 		size_t ap_len;
+		int cur_state;
 
 		ap_len = strlen(ap->path);
 
@@ -411,6 +414,7 @@ static int umount_subtree_mounts(struct 
 		else
 			base = me->key + strlen(root);
 
+		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 		/* Lock the closest parent nesting point for umount */
 		cache_multi_lock(me->parent);
 		if (umount_multi_triggers(ap, root, me, base)) {
@@ -419,9 +423,10 @@ static int umount_subtree_mounts(struct 
 			left++;
 		}
 		cache_multi_unlock(me->parent);
+		pthread_setcancelstate(cur_state, NULL);
 	}
 
-	cache_unlock(mc);
+	pthread_cleanup_pop(1);
 
 	if (left || is_autofs_fs)
 		return left;
@@ -616,8 +621,10 @@ static int get_pkt(struct autofs_point *
 
 			if (post_state != ST_INVAL) {
 				if (post_state == ST_SHUTDOWN_PENDING ||
-				    post_state == ST_SHUTDOWN_FORCE)
+				    post_state == ST_SHUTDOWN_FORCE) {
+					alarm_delete(ap);
 					st_remove_tasks(ap);
+				}
 				st_add_task(ap, post_state);
 			}
 
@@ -947,7 +954,7 @@ static int do_hup_signal(struct master *
 static void *statemachine(void *arg)
 {
 	sigset_t signalset;
-	int sig, status;
+	int sig;
 
 	sigfillset(&signalset);
 	sigdelset(&signalset, SIGCHLD);
@@ -956,20 +963,9 @@ static void *statemachine(void *arg)
 	while (1) {
 		sigwait(&signalset, &sig);
 
-		status = pthread_mutex_lock(&master_mutex);
-		if (status)
-			fatal(status);
 
-		if (list_empty(&master_list->mounts)) {
-			status = pthread_mutex_unlock(&master_mutex);
-			if (status)
-				fatal(status);
+		if (master_list_empty(master_list))
 			return NULL;
-		}
-
-		status = pthread_mutex_unlock(&master_mutex);
-		if (status)
-			fatal(status);
 
 		switch (sig) {
 		case SIGTERM:
@@ -1068,6 +1064,9 @@ static void handle_mounts_cleanup(void *
 	/* If we have been canceled then we may hold the state mutex. */
 	mutex_operation_wait(&ap->state_mutex);
 
+	alarm_delete(ap);
+	st_remove_tasks(ap);
+
 	umount_autofs(ap, 1);
 
 	master_signal_submount(ap, MASTER_SUBMNT_JOIN);
@@ -1117,6 +1116,7 @@ void *handle_mounts(void *arg)
 		suc.status = 1;
 		state_mutex_unlock(ap);
 		umount_autofs(ap, 1);
+		pthread_setcancelstate(cancel_state, NULL);
 		pthread_exit(NULL);
 	}
 
@@ -1132,7 +1132,7 @@ void *handle_mounts(void *arg)
 		alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq);
 
 	pthread_cleanup_push(handle_mounts_cleanup, ap);
-	pthread_setcancelstate(cancel_state, &cancel_state);
+	pthread_setcancelstate(cancel_state, NULL);
 
 	state_mutex_unlock(ap);
 
diff --git a/daemon/direct.c b/daemon/direct.c
index b08cbdd..9a1cd59 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -758,7 +758,12 @@ static int expire_direct(int ioctlfd, co
 		nanosleep(&tm, NULL);
 	}
 
-	return (retries >= 0);
+	if (!ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
+		if (!ret)
+			return 0;
+	}
+
+	return 1;
 }
 
 static void mnts_cleanup(void *arg)
@@ -770,7 +775,7 @@ static void mnts_cleanup(void *arg)
 
 void *expire_proc_direct(void *arg)
 {
-	struct mnt_list *mnts, *next;
+	struct mnt_list *mnts = NULL, *next;
 	struct expire_args *ea;
 	struct autofs_point *ap;
 	struct mapent *me = NULL;
@@ -786,7 +791,7 @@ void *expire_proc_direct(void *arg)
 
 	ap = ea->ap;
 	now = ea->when;
-	ea->status = 1;
+	ea->status = -1;
 
 	ea->signaled = 1;
 	status = pthread_cond_signal(&ea->cond);
@@ -807,8 +812,8 @@ void *expire_proc_direct(void *arg)
 	left = 0;
 
 	/* Get a list of real mounts and expire them if possible */
-	mnts = get_mnt_list(_PROC_MOUNTS, "/", 0);
 	pthread_cleanup_push(mnts_cleanup, mnts);
+	mnts = get_mnt_list(_PROC_MOUNTS, "/", 0);
 	for (next = mnts; next; next = next->next) {
 		if (!strcmp(next->fs_type, "autofs")) {
 			/*
@@ -828,6 +833,9 @@ void *expire_proc_direct(void *arg)
 				continue;
 		}
 
+		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
+			pthread_testcancel();
+
 		/*
 		 * All direct mounts must be present in the map
 		 * entry cache.
@@ -857,7 +865,9 @@ void *expire_proc_direct(void *arg)
 
 	ea->status = left;
 
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	pthread_cleanup_pop(1);
+	pthread_setcancelstate(cur_state, NULL);
 
 	return NULL;
 }
@@ -1361,6 +1371,7 @@ int handle_packet_missing_direct(struct 
 
 	cache_unlock(mc);
 	pthread_cleanup_push(pending_cleanup, mt);
+	pthread_setcancelstate(state, NULL);
 
 	mt->signaled = 0;
 	while (!mt->signaled) {
diff --git a/daemon/indirect.c b/daemon/indirect.c
index cff4f1c..38d0b7a 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -399,7 +399,12 @@ static int expire_indirect(struct autofs
 		nanosleep(&tm, NULL);
 	}
 
-	return (retries >= 0);
+	if (!ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
+		if (!ret)
+			return 0;
+	}
+
+	return 1;
 }
 
 static void mnts_cleanup(void *arg)
@@ -413,7 +418,7 @@ void *expire_proc_indirect(void *arg)
 {
 	struct autofs_point *ap;
 	struct mapent *me = NULL;
-	struct mnt_list *mnts, *next;
+	struct mnt_list *mnts = NULL, *next;
 	struct expire_args *ea;
 	unsigned int now;
 	int offsets, submnts, count;
@@ -428,7 +433,7 @@ void *expire_proc_indirect(void *arg)
 
 	ap = ea->ap;
 	now = ea->when;
-	ea->status = 1;
+	ea->status = -1;
 
 	ea->signaled = 1;
 	status = pthread_cond_signal(&ea->cond);
@@ -449,8 +454,8 @@ void *expire_proc_indirect(void *arg)
 	left = 0;
 
 	/* Get a list of real mounts and expire them if possible */
-	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0);
 	pthread_cleanup_push(mnts_cleanup, mnts);
+	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0);
 	for (next = mnts; next; next = next->next) {
 		char *ind_key;
 		int ret;
@@ -468,6 +473,9 @@ void *expire_proc_indirect(void *arg)
 			continue;
 		}
 
+		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
+			pthread_testcancel();
+
 		/*
 		 * If the mount corresponds to an offset trigger then
 		 * the key is the path, otherwise it's the last component.
@@ -554,7 +562,9 @@ void *expire_proc_indirect(void *arg)
 
 	ea->status = left;
 
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	pthread_cleanup_pop(1);
+	pthread_setcancelstate(cur_state, NULL);
 
 	return NULL;
 }
diff --git a/daemon/state.c b/daemon/state.c
index 47fee39..526725b 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -98,14 +98,12 @@ void expire_cleanup(void *arg)
 	struct autofs_point *ap;
 	int statefd;
 	enum states next = ST_INVAL;
-	int success, ret, cur_state;
+	int success, ret;
 
 	ea = (struct expire_args *) arg;
 	ap = ea->ap;
 	success = ea->status;
 
-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-
 	state_mutex_lock(ap);
 
 	debug(ap->logopt,
@@ -179,8 +177,6 @@ #endif
 
 	free(ea);
 
-	pthread_setcancelstate(cur_state, NULL);
-
 	return;
 }
 
@@ -602,12 +598,31 @@ static unsigned int st_expire(struct aut
 	return 0;
 }
 
+static struct state_queue *st_alloc_task(struct autofs_point *ap, enum states state)
+{
+	struct state_queue *task;
+
+	task = malloc(sizeof(struct state_queue));
+	if (!task)
+		return NULL;
+	memset(task, 0, sizeof(struct state_queue));
+
+	task->ap = ap;
+	task->state = state;
+
+	INIT_LIST_HEAD(&task->list);
+	INIT_LIST_HEAD(&task->pending);
+
+	return task;
+}
+
 /* Insert alarm entry on ordered list. */
 int st_add_task(struct autofs_point *ap, enum states state)
 {
 	struct list_head *head;
-	struct list_head *p;
+	struct list_head *p, *q;
 	struct state_queue *new;
+	enum states ap_state;
 	unsigned int empty = 1;
 	int status;
 
@@ -630,23 +645,13 @@ int st_add_task(struct autofs_point *ap,
 	}
 
 	state_mutex_lock(ap);
-	if (ap->state == ST_SHUTDOWN) {
+	ap_state = ap->state;
+	if (ap_state == ST_SHUTDOWN) {
 		state_mutex_unlock(ap);
 		return 1;
 	}
 	state_mutex_unlock(ap);
 
-	new = malloc(sizeof(struct state_queue));
-	if (!new)
-		return 0;
-	memset(new, 0, sizeof(struct state_queue));
-
-	new->ap = ap;
-	new->state = state;
-
-	INIT_LIST_HEAD(&new->list);
-	INIT_LIST_HEAD(&new->pending);
-
 	st_mutex_lock();
 
 	head = &state_queue;
@@ -657,15 +662,48 @@ int st_add_task(struct autofs_point *ap,
 
 		task = list_entry(p, struct state_queue, list);
 
-		if (task->ap == ap) {
-			empty = 0;
-			list_add_tail(&new->pending, &task->pending);
+		if (task->ap != ap)
+			continue;
+
+		empty = 0;
+
+		/* Don't add duplicate shutdown tasks */
+		if (task->state == state &&
+		   (ap_state == ST_SHUTDOWN_PENDING ||
+		    ap_state == ST_SHUTDOWN_FORCE))
 			break;
+
+		/* No pending tasks */
+		if (list_empty(&task->pending)) {
+			new = st_alloc_task(ap, state);
+			if (new)
+				list_add_tail(&new->pending, &task->pending);
+			goto done;
+		}
+
+		list_for_each(q, &task->pending) {
+			struct state_queue *p_task;
+
+			p_task = list_entry(q, struct state_queue, pending);
+
+			if (p_task->state == state &&
+			   (ap_state == ST_SHUTDOWN_PENDING ||
+			    ap_state == ST_SHUTDOWN_FORCE))
+				goto done;
 		}
+
+		new = st_alloc_task(ap, state);
+		if (new)
+			list_add_tail(&new->pending, &task->pending);
+done:
+		break;
 	}
 
-	if (empty)
-		list_add(&new->list, head);
+	if (empty) {
+		new = st_alloc_task(ap, state);
+		if (new)
+			list_add(&new->list, head);
+	}
 
 	/* Added task, encourage state machine */
 	signaled = 1;
@@ -715,8 +753,12 @@ void st_remove_tasks(struct autofs_point
 			waiting = list_entry(q, struct state_queue, pending);
 			q = q->next;
 
-			list_del(&waiting->pending);
-			free(waiting);
+			/* Don't remove existing shutdown task */
+			if (waiting->state != ST_SHUTDOWN_PENDING &&
+			    waiting->state != ST_SHUTDOWN_FORCE) {
+				list_del(&waiting->pending);
+				free(waiting);
+			}
 		}
 	}
 
@@ -735,7 +777,7 @@ static int run_state_task(struct state_q
 {
 	struct autofs_point *ap;
 	enum states next_state, state;
-	unsigned long ret = 1;
+	unsigned long ret = 0;
  
 	ap = task->ap;
 	next_state = task->state;
@@ -767,7 +809,6 @@ static int run_state_task(struct state_q
 			break;
 
 		default:
-			ret = 0;
 			error(ap->logopt, "bad next state %d", next_state);
 		}
 	}
@@ -825,12 +866,7 @@ static void *st_queue_handler(void *arg)
 
 			task = list_entry(p, struct state_queue, list);
 			p = p->next;
-/*
-			debug(LOGOPT_NONE,
-			      "task %p ap %p state %d next %d busy %d",
-			      task, task->ap, task->ap->state,
-			      task->state, task->busy);
-*/
+
 			task->busy = 1;
 
 			ret = run_state_task(task);
@@ -861,12 +897,7 @@ static void *st_queue_handler(void *arg)
 
 				task = list_entry(p, struct state_queue, list);
 				p = p->next;
-/*
-				debug(LOGOPT_NONE,
-				      "task %p ap %p state %d next %d busy %d",
-				      task, task->ap, task->ap->state,
-				      task->state, task->busy);
-*/
+
 				if (!task->busy) {
 					/* Start a new task */
 					task->busy = 1;
diff --git a/include/automount.h b/include/automount.h
index 6153f71..1f4fc6b 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -123,7 +123,7 @@ #define CHE_DUPLICATE	0x0020
 
 #define HASHSIZE		77
 #define NEGATIVE_TIMEOUT	10
-#define UMOUNT_RETRIES		6
+#define UMOUNT_RETRIES		8
 #define EXPIRE_RETRIES		3
 
 struct mapent_cache {
diff --git a/lib/master.c b/lib/master.c
index 1d66542..a411459 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -724,8 +724,8 @@ int master_read_master(struct master *ma
 	master_mutex_lock();
 
 	if (list_empty(&master->mounts)) {
-		error(LOGOPT_ANY, "no mounts in table");
 		master_mutex_unlock();
+		error(LOGOPT_ANY, "no mounts in table");
 		return 0;
 	}
 
@@ -856,8 +856,9 @@ void master_notify_state_change(struct m
 	struct master_mapent *entry;
 	struct autofs_point *ap;
 	struct list_head *p;
-	int state_pipe;
+	int state_pipe, cur_state;
 
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	master_mutex_lock();
 
 	list_for_each(p, &master->mounts) {
@@ -907,6 +908,7 @@ next:
 	}
 
 	master_mutex_unlock();
+	pthread_setcancelstate(cur_state, NULL);
 
 	return;
 }
@@ -1065,7 +1067,9 @@ static void check_update_map_sources(str
 int master_mount_mounts(struct master *master, time_t age, int readall)
 {
 	struct list_head *p, *head;
+	int cur_state;
 
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	master_mutex_lock();
 
 	head = &master->mounts;
@@ -1109,6 +1113,7 @@ int master_mount_mounts(struct master *m
 	}
 
 	master_mutex_unlock();
+	pthread_setcancelstate(cur_state, NULL);
 
 	return 1;
 }
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 3588129..1bfdeed 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1010,7 +1010,7 @@ int lookup_mount(struct autofs_point *ap
 
 	cache_readlock(mc);
 	me = cache_lookup(mc, key);
-	if (me && me->mapent) {
+	if (me && me->mapent && *me->mapent) {
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		mapent_len = strlen(me->mapent);
 		mapent = alloca(mapent_len + 1);
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index c0ced9e..b63539e 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1648,7 +1648,7 @@ int lookup_mount(struct autofs_point *ap
 
 	cache_readlock(mc);
 	me = cache_lookup(mc, key);
-	if (me && me->mapent) {
+	if (me && me->mapent && *me->mapent) {
 		mapent_len = strlen(me->mapent);
 		mapent = alloca(mapent_len + 1);
 		strcpy(mapent, me->mapent);
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index b0fe4a6..683ec6c 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -514,7 +514,7 @@ int lookup_mount(struct autofs_point *ap
 
 	cache_readlock(mc);
 	me = cache_lookup(mc, key);
-	if (me && me->mapent) {
+	if (me && me->mapent && *me->mapent) {
 		mapent_len = strlen(me->mapent);
 		mapent = alloca(mapent_len + 1);
 		strcpy(mapent, me->mapent);
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 275610a..8dfb9c0 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -598,7 +598,7 @@ int lookup_mount(struct autofs_point *ap
 
 	cache_readlock(mc);
 	me = cache_lookup(mc, key);
-	if (me && me->mapent) {
+	if (me && me->mapent && *me->mapent) {
 		mapent_len = strlen(me->mapent);
 		mapent = alloca(mapent_len + 1);
 		strcpy(mapent, me->mapent);
