Module Name:    src
Committed By:   ozaki-r
Date:           Wed Nov 12 03:24:25 UTC 2014

Modified Files:
        src/sys/netinet6: mld6.c

Log Message:
Ensure callout isn't running and pending before callout_destroy

Call callout_halt before callout_destroy. And also let callout (mld_timeo)
not call callout_schedule when we already called callout_halt.

This fixes PR 47881.


To generate a diff of this commit:
cvs rdiff -u -r1.60 -r1.61 src/sys/netinet6/mld6.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.60 src/sys/netinet6/mld6.c:1.61
--- src/sys/netinet6/mld6.c:1.60	Tue Sep  9 20:16:12 2014
+++ src/sys/netinet6/mld6.c	Wed Nov 12 03:24:25 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: mld6.c,v 1.60 2014/09/09 20:16:12 rmind Exp $	*/
+/*	$NetBSD: mld6.c,v 1.61 2014/11/12 03:24:25 ozaki-r Exp $	*/
 /*	$KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $	*/
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.60 2014/09/09 20:16:12 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.61 2014/11/12 03:24:25 ozaki-r Exp $");
 
 #include "opt_inet.h"
 
@@ -195,6 +195,8 @@ mld_starttimer(struct in6_multi *in6m)
 {
 	struct timeval now;
 
+	KASSERT(in6m->in6m_timer != IN6M_TIMER_UNDEF);
+
 	microtime(&now);
 	in6m->in6m_timer_expire.tv_sec = now.tv_sec + in6m->in6m_timer / hz;
 	in6m->in6m_timer_expire.tv_usec = now.tv_usec +
@@ -227,6 +229,9 @@ mld_timeo(void *arg)
 	mutex_enter(softnet_lock);
 	KERNEL_LOCK(1, NULL);
 
+	if (in6m->in6m_timer == IN6M_TIMER_UNDEF)
+		goto out;
+
 	in6m->in6m_timer = IN6M_TIMER_UNDEF;
 
 	switch (in6m->in6m_state) {
@@ -238,6 +243,7 @@ mld_timeo(void *arg)
 		break;
 	}
 
+out:
 	KERNEL_UNLOCK_ONE(NULL);
 	mutex_exit(softnet_lock);
 }
@@ -741,7 +747,12 @@ in6_delmulti(struct in6_multi *in6m)
 		 */
 		sockaddr_in6_init(&sin6, &in6m->in6m_addr, 0, 0, 0);
 		if_mcast_op(in6m->in6m_ifp, SIOCDELMULTI, sin6tosa(&sin6));
+
+		/* Tell mld_timeo we're halting the timer */
+		in6m->in6m_timer = IN6M_TIMER_UNDEF;
+		callout_halt(&in6m->in6m_timer_ch, softnet_lock);
 		callout_destroy(&in6m->in6m_timer_ch);
+
 		free(in6m, M_IPMADDR);
 	}
 	splx(s);

Reply via email to