cli: 'restart' should close open files (VPP-1068)

- On 'restart' close all registered files (except stdio) so that the
  new process has a clean start; in particular, CLI sockets, API
  sockets, tun/af_packet etc descriptors all need to close so they're
  not left open but unused by the new VPP process. To do this we iterate
  all the files registered for the polling mechanism and close() them.[1]
- While we're here, retain the original environment on 'restart';
  several things make use of it.

[1] An alternative mechanism would be to mark all files with CLOEXEC
  on opening; I think that is a little fragile for this fairly esoteric
  use case.

Change-Id: I81b4e261c4d3c4e2948981231be899824dd4e69f
Signed-off-by: Chris Luke <chrisy@flirble.org>
diff --git a/src/vlib/cli.c b/src/vlib/cli.c
index a85fa93..f684289 100644
--- a/src/vlib/cli.c
+++ b/src/vlib/cli.c
@@ -38,6 +38,7 @@
  */
 
 #include <vlib/vlib.h>
+#include <vlib/unix/unix.h>
 #include <vppinfra/cpu.h>
 #include <unistd.h>
 #include <ctype.h>
@@ -905,9 +906,23 @@
 restart_cmd_fn (vlib_main_t * vm, unformat_input_t * input,
 		vlib_cli_command_t * cmd)
 {
-  char *newenviron[] = { NULL };
+  clib_file_main_t *fm = &file_main;
+  clib_file_t *f;
 
-  execve (vm->name, (char **) vm->argv, newenviron);
+  /* environ(7) does not indicate a header for this */
+  extern char **environ;
+
+  /* Close all known open files */
+  /* *INDENT-OFF* */
+  pool_foreach(f, fm->file_pool,
+    ({
+      if (f->file_descriptor > 2)
+        close(f->file_descriptor);
+    }));
+  /* *INDENT-ON* */
+
+  /* Exec ourself */
+  execve (vm->name, (char **) vm->argv, environ);
 
   return 0;
 }