summaryrefslogtreecommitdiffstats
path: root/src/vlib
diff options
context:
space:
mode:
authorDave Barach <dbarach@cisco.com>2017-12-15 12:22:57 -0500
committerJohn Lo <loj@cisco.com>2017-12-15 22:32:11 +0000
commit2877eee189993dbd1b9a5c3d22499930a4768786 (patch)
tree7c106163b2595a06441c329a2781537929296bc9 /src/vlib
parent891f0a1caa795ed7799f0c6faa1cb91b4669d4da (diff)
VPP-1102: fix dangling references in RPC handling
Queue RPC calls and send them from the main dispatch loop. As things stood, if the vpp main input queue filled, worker threads could enter a barrier-sync spin-wait in the middle of processing a frame. If thread 0 decided to recreate worker thread data structures, the worker thread(s) could easily crash. Legislate the problem out of existence by enqueueing RPC messages only from the main dispatch loop. At that point, doing a barrier-sync wait is perfectly OK. Change-Id: I18da3e44bb1f29a63fe5f30cf11de732ecfd5bf7 Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'src/vlib')
-rw-r--r--src/vlib/main.c13
-rw-r--r--src/vlib/main.h3
-rw-r--r--src/vlib/threads.c3
3 files changed, 19 insertions, 0 deletions
diff --git a/src/vlib/main.c b/src/vlib/main.c
index fd9937fe3e6..d32ca7b8ea2 100644
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -1423,6 +1423,13 @@ dispatch_suspended_process (vlib_main_t * vm,
return t;
}
+void vl_api_send_pending_rpc_requests (vlib_main_t *) __attribute__ ((weak));
+void
+vl_api_send_pending_rpc_requests (vlib_main_t * vm)
+{
+}
+
+
static_always_inline void
vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
{
@@ -1475,6 +1482,9 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
{
vlib_node_runtime_t *n;
+ if (PREDICT_FALSE (_vec_len (vm->pending_rpc_requests) > 0))
+ vl_api_send_pending_rpc_requests (vm);
+
if (!is_main)
{
vlib_worker_thread_barrier_check ();
@@ -1742,6 +1752,9 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
10e-6 /* timer period 10us */ ,
~0 /* max expirations per call */ );
+ vec_validate (vm->pending_rpc_requests, 0);
+ _vec_len (vm->pending_rpc_requests) = 0;
+
switch (clib_setjmp (&vm->main_loop_exit, VLIB_MAIN_LOOP_EXIT_NONE))
{
case VLIB_MAIN_LOOP_EXIT_NONE:
diff --git a/src/vlib/main.h b/src/vlib/main.h
index 4288d6f0388..28412e823a9 100644
--- a/src/vlib/main.h
+++ b/src/vlib/main.h
@@ -210,6 +210,9 @@ typedef struct vlib_main_t
/* Earliest barrier can be closed again */
f64 barrier_no_close_before;
+ /* Vector of pending RPC requests */
+ uword *pending_rpc_requests;
+
} vlib_main_t;
/* Global main structure. */
diff --git a/src/vlib/threads.c b/src/vlib/threads.c
index be8daa64c0a..3edf1ebbc62 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -830,6 +830,9 @@ start_workers (vlib_main_t * vm)
vm_clone->mbuf_alloc_list = 0;
vm_clone->init_functions_called =
hash_create (0, /* value bytes */ 0);
+ vm_clone->pending_rpc_requests = 0;
+ vec_validate (vm_clone->pending_rpc_requests, 0);
+ _vec_len (vm_clone->pending_rpc_requests) = 0;
memset (&vm_clone->random_buffer, 0,
sizeof (vm_clone->random_buffer));