]> git.proxmox.com Git - mirror_ovs.git/commitdiff
fatal-signal: Log backtrace when no monitor daemon.
authorWilliam Tu <u9012063@gmail.com>
Mon, 23 Mar 2020 14:44:48 +0000 (07:44 -0700)
committerWilliam Tu <u9012063@gmail.com>
Mon, 23 Mar 2020 16:43:06 +0000 (09:43 -0700)
Currently the backtrace logging is only available when monitor
daemon is running.  This patch enables backtrace logging when
no monitor daemon exists.  At signal handling context, it detects
whether monitor daemon exists.  If not, write directly the backtrace
to the vlog fd.  Note that using VLOG_* macro doesn't work due to
it's buffer I/O, so this patch directly issue write() syscall to
the file descriptor.

For some system we stop using monitor daemon and use systemd to
monitor ovs-vswitchd, thus need this patch. Example of
ovs-vswitchd.log (note that there is no timestamp printed):
  2020-03-23T14:42:12.949Z|00049|memory|INFO|175332 kB peak resident
  2020-03-23T14:42:12.949Z|00050|memory|INFO|handlers:2 ports:3 reva
  SIGSEGV detected, backtrace:
  0x0000000000486969 <fatal_signal_handler+0x49>
  0x00007f7f5e57f4b0 <killpg+0x40>
  0x000000000047daa8 <pmd_thread_main+0x238>
  0x0000000000504edd <ovsthread_wrapper+0x7d>
  0x00007f7f5f0476ba <start_thread+0xca>
  0x00007f7f5e65141d <clone+0x6d>
  0x0000000000000000 <+0x0>

Acked-by: Ben Pfaff <blp@ovn.org>
Signed-off-by: William Tu <u9012063@gmail.com>
include/openvswitch/vlog.h
lib/daemon-private.h
lib/daemon-unix.c
lib/fatal-signal.c
lib/vlog.c

index 19da4ab62320083c61de9f99246ccc3994a56b13..476bf3d6d5b49cb3bc7c899f5d99308d0807f0e4 100644 (file)
@@ -143,6 +143,9 @@ void vlog_set_syslog_method(const char *method);
 /* Configure syslog target. */
 void vlog_set_syslog_target(const char *target);
 
+/* Return the log_fd. */
+int vlog_get_fd(void);
+
 /* Initialization. */
 void vlog_init(void);
 void vlog_enable_async(void);
index 4e0667601001239e3381dc602206a79a2e22232b..2b90e004235c1bb9ad73bdd99b91abb16e7392d6 100644 (file)
@@ -20,6 +20,7 @@
 extern bool detach;
 extern char *pidfile;
 extern int daemonize_fd;
+extern bool monitor;
 
 char *make_pidfile_name(const char *name);
 
index 6b2a5b9bd4e6f74f51f2bd6d79d82bcd2ea11e24..ae59ecf2c2b515531219b670cc18a86e1dda26ab 100644 (file)
@@ -80,7 +80,7 @@ int daemonize_fd = -1;
 
 /* --monitor: Should a supervisory process monitor the daemon and restart it if
  * it dies due to an error signal? */
-static bool monitor;
+bool monitor;
 
 /* --user: Only root can use this option. Switch to new uid:gid after
  * initially running as root.  */
index ba7f5bfd314d654b7aa6137cc6502537d14bc24c..4965c1ae82c07f0be81cae23f371d6fa261e056a 100644 (file)
@@ -187,7 +187,32 @@ send_backtrace_to_monitor(void) {
         dep++;
     }
 
-    ignore(write(daemonize_fd, unw_bt, dep * sizeof(struct unw_backtrace)));
+    if (monitor) {
+        ignore(write(daemonize_fd, unw_bt,
+                     dep * sizeof(struct unw_backtrace)));
+    } else {
+        /* Since there is no monitor daemon running, write backtrace
+         * in current process.  This is not asyn-signal-safe due to
+         * use of snprintf().
+         */
+        char str[] = "SIGSEGV detected, backtrace:\n";
+
+        if (vlog_get_fd() < 0) {
+            return;
+        }
+
+        ignore(write(vlog_get_fd(), str, strlen(str)));
+
+        for (int i = 0; i < dep; i++) {
+            char line[64];
+
+            snprintf(line, 64, "0x%016"PRIxPTR" <%s+0x%"PRIxPTR">\n",
+                     unw_bt[i].ip,
+                     unw_bt[i].func,
+                     unw_bt[i].offset);
+            ignore(write(vlog_get_fd(), line, strlen(line)));
+        }
+    }
 }
 #else
 static inline void
index 559943d87937722046fb2b1f21dc238eee6be1d1..502b33fc831e8ff384a284bdca3776f2d1626ada 100644 (file)
@@ -612,6 +612,12 @@ vlog_set_syslog_target(const char *target)
     ovs_rwlock_unlock(&pattern_rwlock);
 }
 
+int
+vlog_get_fd(void)
+{
+    return log_fd;
+}
+
 /* Returns 'false' if 'facility' is not a valid string. If 'facility'
  * is a valid string, sets 'value' with the integer value of 'facility'
  * and returns 'true'. */