#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
/** Default CLI pager limit is not configured in startup.conf */
#define UNIX_CLI_DEFAULT_PAGER_LIMIT 100000
/** Default CLI history depth if not configured in startup.conf */
#define UNIX_CLI_DEFAULT_HISTORY 50
+char *vlib_default_runtime_dir __attribute__ ((weak));
+char *vlib_default_runtime_dir = "vlib";
unix_main_t unix_main;
+clib_file_main_t file_main;
static clib_error_t *
unix_main_init (vlib_main_t * vm)
static void
unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
{
- uword fatal;
+ uword fatal = 0;
u8 *msg = 0;
msg = format (msg, "received signal %U, PC %U",
if (unix_main.vlib_main->main_loop_exit_set)
{
syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting...");
-
- clib_longjmp (&unix_main.vlib_main->main_loop_exit,
- VLIB_MAIN_LOOP_EXIT_CLI);
+ unix_main.vlib_main->main_loop_exit_now = 1;
}
+ break;
/* fall through */
case SIGQUIT:
case SIGINT:
{
unix_main_t *um = &unix_main;
clib_error_t *error = 0;
+ gid_t gid;
+ int pidfd = -1;
/* Defaults */
um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT;
else
if (unformat (input, "cli-listen %s", &um->cli_listen_socket.config))
;
+ else if (unformat (input, "runtime-dir %s", &um->runtime_dir))
+ ;
else if (unformat (input, "cli-line-mode"))
um->cli_line_mode = 1;
else if (unformat (input, "cli-no-banner"))
else
if (unformat (input, "cli-history-limit %d", &um->cli_history_limit))
;
+ else if (unformat (input, "coredump-size"))
+ {
+ uword coredump_size = 0;
+ if (unformat (input, "unlimited"))
+ {
+ coredump_size = RLIM_INFINITY;
+ }
+ else
+ if (!unformat (input, "%U", unformat_memory_size, &coredump_size))
+ {
+ return clib_error_return (0,
+ "invalid coredump-size parameter `%U'",
+ format_unformat_error, input);
+ }
+ const struct rlimit new_limit = { coredump_size, coredump_size };
+ if (0 != setrlimit (RLIMIT_CORE, &new_limit))
+ {
+ clib_unix_warning ("prlimit() failed");
+ }
+ }
else if (unformat (input, "full-coredump"))
{
int fd;
vec_free (lv);
}
}
+ else if (unformat (input, "gid %U", unformat_unix_gid, &gid))
+ {
+ if (setegid (gid) == -1)
+ return clib_error_return_unix (0, "setegid");
+ }
+ else if (unformat (input, "pidfile %s", &um->pidfile))
+ ;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
}
- if (!(um->flags & UNIX_FLAG_INTERACTIVE))
+ if (um->runtime_dir == 0)
+ {
+ uid_t uid = geteuid ();
+ if (uid == 00)
+ um->runtime_dir = format (0, "/run/%s%c",
+ vlib_default_runtime_dir, 0);
+ else
+ um->runtime_dir = format (0, "/run/user/%u/%s%c", uid,
+ vlib_default_runtime_dir, 0);
+ }
+
+ error = setup_signal_handlers (um);
+ if (error)
+ return error;
+
+ if (um->pidfile)
{
- error = setup_signal_handlers (um);
- if (error)
+ if ((error = vlib_unix_validate_runtime_file (um,
+ (char *) um->pidfile,
+ &um->pidfile)))
return error;
+ if (((pidfd = open ((char *) um->pidfile,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0))
+ {
+ return clib_error_return_unix (0, "open");
+ }
+ }
+
+ if (!(um->flags & UNIX_FLAG_INTERACTIVE))
+ {
openlog (vm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);
clib_error_register_handler (unix_error_handler, um);
0) < 0)
clib_error_return (0, "daemon () fails");
}
+
+ if (pidfd >= 0)
+ {
+ u8 *lv = format (0, "%d", getpid ());
+ if (write (pidfd, (char *) lv, vec_len (lv)) != vec_len (lv))
+ {
+ vec_free (lv);
+ close (pidfd);
+ return clib_error_return_unix (0, "write");
+ }
+ vec_free (lv);
+ close (pidfd);
+ }
+
um->unix_config_complete = 1;
return 0;
* Very useful in situations where folks don't remember or can't be bothered
* to include CLI commands in bug reports.
*
+ * @cfgcmd{pidfile, <filename>}
+ * Writes the pid of the main thread in @c filename.
+ *
* @cfgcmd{full-coredump}
* Ask the Linux kernel to dump all memory-mapped address regions, instead
* of just text+data+bss.
*
+ * @cfgcmd{runtime-dir}
+ * Define directory where VPP is going to store all runtime files.
+ * Default is /run/vpp.
+ *
* @cfgcmd{cli-listen, <address:port>}
* Bind the CLI to listen at the address and port given. @clocalhost
* on TCP port @c 5002, given as <tt>cli-listen localhost:5002</tt>,
* Limit pager buffer to @c nn lines of output.
* A value of @c 0 disables the pager. Default value: @c 100000
?*/
-VLIB_CONFIG_FUNCTION (unix_config, "unix");
+VLIB_EARLY_CONFIG_FUNCTION (unix_config, "unix");
static clib_error_t *
unix_exit (vlib_main_t * vm)
return i;
}
+u8 *
+vlib_thread_stack_init (uword thread_index)
+{
+ vec_validate (vlib_thread_stacks, thread_index);
+ vlib_thread_stacks[thread_index] = clib_mem_alloc_aligned
+ (VLIB_THREAD_STACK_SIZE, VLIB_THREAD_STACK_SIZE);
+
+ /*
+ * Disallow writes to the bottom page of the stack, to
+ * catch stack overflows.
+ */
+ if (mprotect (vlib_thread_stacks[thread_index],
+ clib_mem_get_page_size (), PROT_READ) < 0)
+ clib_unix_warning ("thread stack");
+ return vlib_thread_stacks[thread_index];
+}
+
int
vlib_unix_main (int argc, char *argv[])
{
vlib_main_t *vm = &vlib_global_main; /* one and only time for this! */
- vlib_thread_main_t *tm = &vlib_thread_main;
unformat_input_t input;
- u8 *thread_stacks;
clib_error_t *e;
int i;
vm->heap_base = clib_mem_get_heap ();
ASSERT (vm->heap_base);
+ unformat_init_command_line (&input, (char **) vm->argv);
+ if ((e = vlib_plugin_config (vm, &input)))
+ {
+ clib_error_report (e);
+ return 1;
+ }
+ unformat_free (&input);
+
i = vlib_plugin_early_init (vm);
if (i)
return i;
}
unformat_free (&input);
- /*
- * allocate n x VLIB_THREAD_STACK_SIZE stacks, aligned to a
- * VLIB_THREAD_STACK_SIZE boundary
- * See also: os_get_cpu_number() in vlib/vlib/threads.c
- */
- thread_stacks = clib_mem_alloc_aligned
- ((uword) tm->n_thread_stacks * VLIB_THREAD_STACK_SIZE,
- VLIB_THREAD_STACK_SIZE);
-
- vec_validate (vlib_thread_stacks, tm->n_thread_stacks - 1);
- for (i = 0; i < vec_len (vlib_thread_stacks); i++)
- {
- vlib_thread_stacks[i] = thread_stacks;
-
- /*
- * Disallow writes to the bottom page of the stack, to
- * catch stack overflows.
- */
- if (mprotect (thread_stacks, clib_mem_get_page_size (), PROT_READ) < 0)
- clib_unix_warning ("thread stack");
+ vlib_thread_stack_init (0);
- thread_stacks += VLIB_THREAD_STACK_SIZE;
- }
+ __os_thread_index = 0;
+ vm->thread_index = 0;
i = clib_calljmp (thread0, (uword) vm,
(void *) (vlib_thread_stacks[0] +