On 21/07/16(Thu) 17:22, Dimitris Papastamos wrote:
> On Thu, Jul 21, 2016 at 11:27:17AM +0100, Stuart Henderson wrote:
> > On 2016/07/21 11:16, Dimitris Papastamos wrote:
> > > Hi,
> > > 
> > > I use tinc-vpn on my laptop and noticed that when I reboot or halt
> > > the system, it freezes when it tries to stop the tinc daemon.
> > > 
> > > This is reproducible with today's current.
> > 
> > Would you notice if it was a panic rather than a freeze?
> 
> Ok, so I reproduced it and entered ddb.  I typed the trace
> output below.

Thanks for your help tracking this down.  The problem is that we try
to delete a route that is no longer in the tree and since the loop
didn't check for the return error we try indefinitely.

Diff below fixes that for me.


Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.312
diff -u -p -r1.312 route.c
--- net/route.c 19 Jul 2016 10:26:41 -0000      1.312
+++ net/route.c 22 Jul 2016 09:26:25 -0000
@@ -688,8 +688,9 @@ rtflushclone1(struct rtentry *rt, void *
                return 0;
 
        if (ISSET(rt->rt_flags, RTF_CLONED) && rtequal(rt->rt_parent, parent)) {
-               rtdeletemsg(rt, ifp, id);
-               error = EAGAIN;
+               error = rtdeletemsg(rt, ifp, id);
+               if (error == 0)
+                       error = EAGAIN;
        } else
                error = 0;
 
@@ -1725,13 +1726,16 @@ int
 rt_if_remove_rtdelete(struct rtentry *rt, void *vifp, u_int id)
 {
        struct ifnet    *ifp = vifp;
+       int              error;
 
-       if (rt->rt_ifidx == ifp->if_index) {
-               rtdeletemsg(rt, ifp, id);
-               return (EAGAIN);
-       }
+       if (rt->rt_ifidx != ifp->if_index)
+               return (0);
+
+       if ((error = rtdeletemsg(rt, ifp, id)))
+               return (error);
+
+       return (EAGAIN);
 
-       return (0);
 }
 
 #ifndef SMALL_KERNEL
@@ -1785,7 +1789,10 @@ rt_if_linkstate_change(struct rtentry *r
                         * new routes from a better source.
                         */
                        if (ISSET(rt->rt_flags, RTF_CLONED|RTF_DYNAMIC)) {
-                               rtdeletemsg(rt, ifp, id);
+                               int error;
+
+                               if ((error = rtdeletemsg(rt, ifp, id)))
+                                       return (error);
                                return (EAGAIN);
                        }
                        /* take route down */

Reply via email to