diff mbox series

[ovs-dev,25/62] fatal-signal: Log backtrace when no monitor daemon.

Message ID 20201228092520.11807-26-taoyunxiang@cmss.chinamobile.com
State Not Applicable
Headers show
Series [ovs-dev] db-ctl-base: add uuid specified method for create cmd | expand

Commit Message

Tao YunXiang Dec. 28, 2020, 9:24 a.m. UTC
From: Rongyin <rongyin@cmss.chinamobile.com>

    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>

Code Source From: Self Code

Description:

    see above

Jira:  #[Optional]
市场项目编号(名称):[Optional]
---
 include/openvswitch/vlog.h |  3 +++
 lib/daemon-private.h       |  1 +
 lib/daemon-unix.c          |  2 +-
 lib/fatal-signal.c         | 27 ++++++++++++++++++++++++++-
 lib/vlog.c                 |  6 ++++++
 5 files changed, 37 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/include/openvswitch/vlog.h b/include/openvswitch/vlog.h
index 19da4ab..476bf3d 100644
--- a/include/openvswitch/vlog.h
+++ b/include/openvswitch/vlog.h
@@ -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);
diff --git a/lib/daemon-private.h b/lib/daemon-private.h
index 4e06676..2b90e00 100644
--- a/lib/daemon-private.h
+++ b/lib/daemon-private.h
@@ -20,6 +20,7 @@ 
 extern bool detach;
 extern char *pidfile;
 extern int daemonize_fd;
+extern bool monitor;
 
 char *make_pidfile_name(const char *name);
 
diff --git a/lib/daemon-unix.c b/lib/daemon-unix.c
index 7e48630..e073b89 100644
--- a/lib/daemon-unix.c
+++ b/lib/daemon-unix.c
@@ -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.  */
diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c
index 09f7c6e..3a72a2f 100644
--- a/lib/fatal-signal.c
+++ b/lib/fatal-signal.c
@@ -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
diff --git a/lib/vlog.c b/lib/vlog.c
index 559943d..502b33f 100644
--- a/lib/vlog.c
+++ b/lib/vlog.c
@@ -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'. */