It is possible that a session is going down while peer->rpending (the flag
indicating that there is more data to process) is set. If that is
happening the session engine is spinning until the session comes back up
or the neighbor is removed.

Fix is obvious, clear the flag when the read buffer rbuf is set to NULL.
Additionally ensure that the timeout is only set to 0 if there is
something in the read buffer to process.
-- 
:wq Claudio

Index: session.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
retrieving revision 1.386
diff -u -p -r1.386 session.c
--- session.c   22 Jun 2019 05:36:40 -0000      1.386
+++ session.c   28 Jun 2019 07:43:11 -0000
@@ -422,7 +422,7 @@ session_main(int debug, int verbose)
                        if (p->wbuf.queued > 0 || p->state == STATE_CONNECT)
                                events |= POLLOUT;
                        /* is there still work to do? */
-                       if (p->rpending)
+                       if (p->rpending && p->rbuf && p->rbuf->wpos)
                                timeout = 0;
 
                        /* poll events */
@@ -888,6 +888,7 @@ change_state(struct peer *peer, enum ses
                msgbuf_clear(&peer->wbuf);
                free(peer->rbuf);
                peer->rbuf = NULL;
+               peer->rpending = 0;
                bzero(&peer->capa.peer, sizeof(peer->capa.peer));
                if (!peer->template)
                        imsg_compose(ibuf_main, IMSG_PFKEY_RELOAD,
@@ -2959,6 +2960,7 @@ getpeerbyip(struct bgpd_config *c, struc
                newpeer->state = newpeer->prev_state = STATE_NONE;
                newpeer->reconf_action = RECONF_KEEP;
                newpeer->rbuf = NULL;
+               newpeer->rpending = 0;
                init_peer(newpeer);
                bgp_fsm(newpeer, EVNT_START);
                if (RB_INSERT(peer_head, &c->peers, newpeer) != NULL)

Reply via email to