Sunday, May 28, 2017

[389-commits] [389-ds-base] 01/01: Ticket 49242 - add gdb script to rpm

This is an automated email from the git hooks/post-receive script.

firstyear pushed a commit to branch master
in repository 389-ds-base.

commit 5ecd8ec2847d004d7054650f061589d131cd3b32
Author: William Brown <firstyear@redhat.com>
Date: Thu May 4 12:00:25 2017 +1000

Ticket 49242 - add gdb script to rpm

Bug Description: DS is hard to debug, and often has many threads.

Fix Description: To make this easier for support and users to
work through issues, this gdb script allows automatic elimination
of idle threads, and dumps the inmemory access log.

https://pagure.io/389-ds-base/issue/49242

Author: wibrown

Review by: vashirov, lkrispen, (Thanks)
---
Makefile.am | 4 ++
ldap/admin/src/scripts/ns-slapd-gdb.py | 120 +++++++++++++++++++++++++++++++++
rpm/389-ds-base.spec.in | 2 +
3 files changed, 126 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 5f3af07..6f9c1c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -267,6 +267,7 @@ mibdir = $(datadir)@mibdir@
updatedir = $(datadir)@updatedir@
pkgconfigdir = $(libdir)/pkgconfig
serverincdir = $(includedir)/@serverincdir@
+gdbautoloaddir = $(prefixdir)/share/gdb/auto-load$(sbindir)

defaultuser=@defaultuser@
defaultgroup=@defaultgroup@
@@ -564,6 +565,7 @@ dist_noinst_DATA = \
$(srcdir)/ldap/admin/src/scripts/*.pm \
$(srcdir)/ldap/admin/src/scripts/*.py \
$(srcdir)/ldap/admin/src/scripts/*.sh \
+ $(srcdir)/ldap/admin/src/scripts/ds-replcheck \
$(srcdir)/ldap/admin/src/scripts/migrate-ds.res \
$(srcdir)/ldap/ldif/*.in \
$(srcdir)/ldap/ldif/*.ldif \
@@ -767,6 +769,8 @@ perl_DATA = ldap/admin/src/scripts/SetupLog.pm \
python_DATA = ldap/admin/src/scripts/failedbinds.py \
ldap/admin/src/scripts/logregex.py

+gdbautoload_DATA = ldap/admin/src/scripts/ns-slapd-gdb.py
+
property_DATA = ldap/admin/src/scripts/setup-ds.res \
ldap/admin/src/scripts/migrate-ds.res

diff --git a/ldap/admin/src/scripts/ns-slapd-gdb.py b/ldap/admin/src/scripts/ns-slapd-gdb.py
new file mode 100644
index 0000000..c279d4b
--- /dev/null
+++ b/ldap/admin/src/scripts/ns-slapd-gdb.py
@@ -0,0 +1,120 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+
+##################################################
+#
+# Usage: when using gdb, these commands are automatically loaded with ns-slapd.
+#
+# else, from inside gdb run "source /path/to/ns-slapd-gdb.py"
+#
+
+import itertools
+import re
+
+import gdb
+from gdb.FrameDecorator import FrameDecorator
+
+class DSAccessLog (gdb.Command):
+ """Display the Directory Server access log."""
+ def __init__ (self):
+ super (DSAccessLog, self).__init__ ("ds-access-log", gdb.COMMAND_DATA)
+
+ def invoke (self, arg, from_tty):
+ print('===== BEGIN ACCESS LOG =====')
+ gdb.execute('set print elements 0')
+ o = gdb.execute('p loginfo.log_access_buffer.top', to_string=True)
+ for l in o.split('\\n'):
+ print(l)
+ print('===== END ACCESS LOG =====')
+
+class DSBacktrace(gdb.Command):
+ """Display a filtered backtrace"""
+ def __init__ (self):
+ super (DSBacktrace, self).__init__ ("ds-backtrace", gdb.COMMAND_DATA)
+
+ def _parse_thread_state(self, lwpid, tid):
+ # Stash the BT output
+ o = gdb.execute('bt', to_string=True)
+ # Get to the top of the frame stack.
+ gdb.newest_frame()
+ # Now work our way down.
+ backtrace = []
+ cur_frame = gdb.selected_frame()
+ while cur_frame is not None:
+ backtrace.append(cur_frame.name())
+ cur_frame = cur_frame.older()
+ # Dicts can't use lists as keys, so we need to squash this to a string.
+ s_backtrace = ' '.join(backtrace)
+ # Have we seen this trace before?
+ if s_backtrace not in self._stack_maps:
+ # Make it!
+ self._stack_maps[s_backtrace] = []
+ # Add it to the set.
+ self._stack_maps[s_backtrace].append({'gtid': tid, 'lwpid': lwpid, 'bt': o} )
+
+ def invoke(self, arg, from_tty):
+ print('===== BEGIN ACTIVE THREADS =====')
+
+ # Reset our thread maps.
+ self._stack_maps = {}
+
+ inferiors = gdb.inferiors()
+ for inferior in inferiors:
+ threads = inferior.threads()
+ for thread in threads:
+ (tpid, lwpid, tid) = thread.ptid
+ gtid = thread.num
+ thread.switch()
+ self._parse_thread_state(lwpid, gtid)
+
+ # print (self._stack_maps)
+ for m in self._stack_maps:
+ # Take a copy of the bt
+ o = self._stack_maps[m][0]['bt']
+ # Print every thread and id.
+ for t in self._stack_maps[m]:
+ print("Thread %s (LWP %s))" % (t['gtid'], t['lwpid']))
+ # Print the trace
+ print(o)
+
+ print('===== END ACTIVE THREADS =====')
+
+class DSIdleFilterDecorator(FrameDecorator):
+ def __init__(self, fobj):
+ super(DSIdleFilterDecorator, self).__init__(fobj)
+
+ def function(self):
+ frame = self.inferior_frame()
+ name = str(frame.name())
+
+ if name == 'connection_wait_for_new_work' or name == 'work_q_wait':
+ name = "[IDLE THREAD] " + name
+
+ return name
+
+class DSIdleFilter():
+ def __init__(self):
+ self.name = "DSIdleFilter"
+ self.priority = 100
+ self.enabled = True
+ # Register this frame filter with the global frame_filters
+ # dictionary.
+ gdb.frame_filters[self.name] = self
+
+ def filter(self, frame_iter):
+ # Just return the iterator.
+ if hasattr(itertools, 'imap'):
+ frame_iter = imap(DSIdleFilterDecorator, frame_iter)
+ else:
+ frame_iter = map(DSIdleFilterDecorator, frame_iter)
+ return frame_iter
+
+DSAccessLog()
+DSBacktrace()
+DSIdleFilter()
+
diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in
index d334757..905d70a 100644
--- a/rpm/389-ds-base.spec.in
+++ b/rpm/389-ds-base.spec.in
@@ -288,6 +288,7 @@ make setup.py
%install
rm -rf $RPM_BUILD_ROOT

+mkdir -p %{buildroot}%{_datadir}/gdb/auto-load%{_sbindir}
make DESTDIR="$RPM_BUILD_ROOT" install

# Copy in our docs from doxygen.
@@ -435,6 +436,7 @@ fi
%config(noreplace)%{_sysconfdir}/sysconfig/%{pkgname}
%config(noreplace)%{_sysconfdir}/sysconfig/%{pkgname}.systemd
%{_datadir}/%{pkgname}
+%{_datadir}/gdb/auto-load/*
%{_unitdir}
%{_bindir}/*
# We have to seperate this from being a glob to ensure the caps are applied.

--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
_______________________________________________
389-commits mailing list -- 389-commits@lists.fedoraproject.org
To unsubscribe send an email to 389-commits-leave@lists.fedoraproject.org

No comments:

Post a Comment