summaryrefslogtreecommitdiffstats
path: root/bgpd/bgpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgpd.c')
-rw-r--r--bgpd/bgpd.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 2f50e419..30f32592 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -80,6 +80,9 @@ qpn_nexus routing_nexus = NULL;
/* BGP community-list. */
struct community_list_handler *bgp_clist;
+/* true while program terminating */
+static int program_terminating = 0;
+
/* BGP global flag manipulation. */
int
bgp_option_set (int flag)
@@ -4693,13 +4696,16 @@ bgp_init (void)
}
void
-bgp_terminate (void)
+bgp_terminate (int terminating)
{
struct bgp *bgp;
struct peer *peer;
struct listnode *node, *nnode;
struct listnode *mnode, *mnnode;
+ program_terminating = terminating;
+
+ /* Disable all peers */
for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
bgp_peer_disable(peer, bgp_notify_new(BGP_NOTIFY_CEASE,
@@ -4717,4 +4723,39 @@ bgp_terminate (void)
work_queue_free (bm->process_rsclient_queue);
bm->process_rsclient_queue = NULL;
}
+
+ /* if no sessions were enabled then need to check here */
+ program_terminate_if_all_disabled();
}
+
+/* If we are terminating the program, and all sessions are disabled
+ * then terminate all threads
+ */
+void
+program_terminate_if_all_disabled(void)
+{
+ struct bgp *bgp;
+ struct peer *peer;
+ struct listnode *node, *nnode;
+ struct listnode *mnode, *mnnode;
+
+ if (!program_terminating)
+ return;
+
+ /* are there any active sessions remaining? */
+ for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
+ for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+ if (bgp_session_is_active(peer->session))
+ return;
+
+ /* ask remaining pthreads to die */
+ if (qpthreads_enabled && routing_nexus != NULL)
+ qpn_terminate(routing_nexus);
+
+ if (qpthreads_enabled && bgp_nexus != NULL)
+ qpn_terminate(bgp_nexus);
+
+ if (cli_nexus != NULL)
+ qpn_terminate(cli_nexus);
+}
+