+ return (rv);
+}
+
+static void
+vl_api_memclnt_delete_reply_t_handler (vl_api_memclnt_delete_reply_t * mp)
+{
+ void *oldheap;
+ api_main_t *am = &api_main;
+
+ pthread_mutex_lock (&am->vlib_rp->mutex);
+ oldheap = svm_push_data_heap (am->vlib_rp);
+ svm_queue_free (am->vl_input_queue);
+ pthread_mutex_unlock (&am->vlib_rp->mutex);
+ svm_pop_heap (oldheap);
+
+ am->my_client_index = ~0;
+ am->my_registration = 0;
+ am->vl_input_queue = 0;
+}
+
+void
+vl_client_send_disconnect (u8 do_cleanup)
+{
+ vl_api_memclnt_delete_t *mp;
+ vl_shmem_hdr_t *shmem_hdr;
+ api_main_t *am = &api_main;
+
+ ASSERT (am->vlib_rp);
+ shmem_hdr = am->shmem_hdr;
+ ASSERT (shmem_hdr && shmem_hdr->vl_input_queue);
+
+ mp = vl_msg_api_alloc (sizeof (vl_api_memclnt_delete_t));
+ clib_memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE);
+ mp->index = am->my_client_index;
+ mp->handle = (uword) am->my_registration;
+ mp->do_cleanup = do_cleanup;
+
+ vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
+}
+
+int
+vl_client_disconnect (void)
+{
+ vl_api_memclnt_delete_reply_t *rp;
+ svm_queue_t *vl_input_queue;
+ api_main_t *am = &api_main;
+ time_t begin;
+
+ vl_input_queue = am->vl_input_queue;
+ vl_client_send_disconnect (0 /* wait for reply */ );
+
+ /*
+ * Have to be careful here, in case the client is disconnecting
+ * because e.g. the vlib process died, or is unresponsive.
+ */
+ begin = time (0);
+ while (1)
+ {
+ time_t now;
+
+ now = time (0);
+
+ if (now >= (begin + 2))
+ {
+ clib_warning ("peer unresponsive, give up");
+ am->my_client_index = ~0;
+ am->my_registration = 0;
+ am->shmem_hdr = 0;
+ return -1;
+ }
+ if (svm_queue_sub (vl_input_queue, (u8 *) & rp, SVM_Q_NOWAIT, 0) < 0)
+ continue;
+
+ /* drain the queue */
+ if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY)
+ {
+ clib_warning ("queue drain: %d", ntohs (rp->_vl_msg_id));
+ vl_msg_api_handler ((void *) rp);
+ continue;
+ }
+ vl_msg_api_handler ((void *) rp);
+ break;
+ }
+
+ vl_api_name_and_crc_free ();
+ return 0;
+}
+
+/**
+ * Stave off the binary API dead client reaper
+ * Only sent to inactive clients
+ */
+static void
+vl_api_memclnt_keepalive_t_handler (vl_api_memclnt_keepalive_t * mp)
+{
+ vl_api_memclnt_keepalive_reply_t *rmp;
+ api_main_t *am;
+ vl_shmem_hdr_t *shmem_hdr;
+
+ am = &api_main;
+ shmem_hdr = am->shmem_hdr;
+
+ rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp));
+ clib_memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_MEMCLNT_KEEPALIVE_REPLY);
+ rmp->context = mp->context;
+ vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & rmp);
+}
+
+#define foreach_api_msg \
+_(RX_THREAD_EXIT, rx_thread_exit) \
+_(MEMCLNT_CREATE_REPLY, memclnt_create_reply) \
+_(MEMCLNT_DELETE_REPLY, memclnt_delete_reply) \
+_(MEMCLNT_KEEPALIVE, memclnt_keepalive)
+
+void
+vl_client_install_client_message_handlers (void)
+{