aboutsummaryrefslogtreecommitdiffstats
path: root/vlib/vlib/cli.c
diff options
context:
space:
mode:
authorAndrew Yourtchenko <ayourtch@gmail.com>2016-05-10 10:51:34 +0000
committerDave Barach <openvpp@barachs.net>2016-05-10 17:13:00 +0000
commit716d9593497388c48593f818748faf705ac7169e (patch)
tree50dd1adea16bcff1ab80494532c5603bcf44de5e /vlib/vlib/cli.c
parent46d4e36792e829ef96b43dbc6eec344700d54f13 (diff)
Avoid clobbering output_function by concurrent CLI sessions doing vlib_process_wait_for_event*.
A problem is easily reproducible by taking the test harness code from the commit, and launching it in two terminals with some time overlap - the outputs will be sent to the wrong session. This commit moves the output_function and argument from a global structure into the process structure, thus the output_function is not clobbered anymore and each session gets only its own output. To ensure the callers can redirect the outputs to different destinations (e.g. the API calls via shared memory, etc.) the existing logic for vlib_cli_input() was retained. To avoid the magic numbers usage in the logic that does the page-alignment of the process stack, there are changes around the stack[] member of vlib_process_t. Also added a compile-time assert to ensure that the stack does indeed start on the page size multiple boundary. Change-Id: I128680ac480735e5f214f81a884e414268e5d652 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
Diffstat (limited to 'vlib/vlib/cli.c')
-rw-r--r--vlib/vlib/cli.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/vlib/vlib/cli.c b/vlib/vlib/cli.c
index 8833f4ac261..5a0867bd0f8 100644
--- a/vlib/vlib/cli.c
+++ b/vlib/vlib/cli.c
@@ -506,16 +506,17 @@ void vlib_cli_input (vlib_main_t * vm,
vlib_cli_output_function_t * function,
uword function_arg)
{
+ vlib_process_t * cp = vlib_get_current_process(vm);
vlib_cli_main_t * cm = &vm->cli_main;
clib_error_t * error;
vlib_cli_output_function_t * save_function;
uword save_function_arg;
- save_function = cm->output_function;
- save_function_arg = cm->output_function_arg;
+ save_function = cp->output_function;
+ save_function_arg = cp->output_function_arg;
- cm->output_function = function;
- cm->output_function_arg = function_arg;
+ cp->output_function = function;
+ cp->output_function_arg = function_arg;
do {
vec_reset_length (cm->parse_rule_data);
@@ -529,14 +530,14 @@ void vlib_cli_input (vlib_main_t * vm,
clib_error_free (error);
}
- cm->output_function = save_function;
- cm->output_function_arg = save_function_arg;
+ cp->output_function = save_function;
+ cp->output_function_arg = save_function_arg;
}
/* Output to current CLI connection. */
void vlib_cli_output (vlib_main_t * vm, char * fmt, ...)
{
- vlib_cli_main_t * cm = &vm->cli_main;
+ vlib_process_t * cp = vlib_get_current_process(vm);
va_list va;
u8 * s;
@@ -548,10 +549,10 @@ void vlib_cli_output (vlib_main_t * vm, char * fmt, ...)
if (vec_len (s) > 0 && s[vec_len (s)-1] != '\n')
vec_add1 (s, '\n');
- if (! cm->output_function)
+ if ((! cp) || (! cp->output_function))
fformat (stdout, "%v", s);
else
- cm->output_function (cm->output_function_arg, s, vec_len (s));
+ cp->output_function (cp->output_function_arg, s, vec_len (s));
vec_free (s);
}
@@ -665,6 +666,37 @@ VLIB_CLI_COMMAND (cmd_test_heap_validate,static) = {
.function = test_heap_validate,
};
+#ifdef TEST_CODE
+/*
+ * A trivial test harness to verify the per-process output_function
+ * is working correcty.
+ */
+
+static clib_error_t *
+sleep_ten_seconds (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ u16 i;
+ u16 my_id = rand();
+
+ vlib_cli_output(vm, "Starting 10 seconds sleep with id %u\n", my_id);
+
+ for(i=0; i<10; i++)
+ {
+ vlib_process_wait_for_event_or_clock(vm, 1.0);
+ vlib_cli_output(vm, "Iteration number %u, my id: %u\n", i, my_id);
+ }
+ vlib_cli_output(vm, "Done with sleep with id %u\n", my_id);
+ return 0;
+}
+
+VLIB_CLI_COMMAND (ping_command, static) = {
+ .path = "test sleep",
+ .function = sleep_ten_seconds,
+ .short_help = "Sleep for 10 seconds",
+};
+#endif /* ifdef TEST_CODE */
static uword vlib_cli_normalize_path (char * input, char ** result)
{