summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-01-07 14:36:24 +0100
committerVolker Lendecke <vl@samba.org>2017-01-20 18:48:25 +0100
commit1f6d5f2c090ee6bb6e0215b8cfa365eb96453917 (patch)
tree419e53040c4b4a0d91bc5c5c94fa5ff27d66f317 /lib
parentbf59d97f80a7894672a46a312259cc4118576637 (diff)
downloadsamba-1f6d5f2c090ee6bb6e0215b8cfa365eb96453917.tar.gz
debug: add "ringbuf" backend logging to a ringbuffer
This is useful for debugging bugs that involve timing effects and are not reproducible when logging at higher debug levels with the file backend. The log can be dumped to a file with gdb: (gdb) dump binary memory samba.log debug_ringbuf debug_ringbuf+SIZE Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Volker Lendecke <vl@samba.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/util/debug.c83
-rw-r--r--lib/util/debug.h3
2 files changed, 86 insertions, 0 deletions
diff --git a/lib/util/debug.c b/lib/util/debug.c
index 12a9b1bcaaa..08954c30fde 100644
--- a/lib/util/debug.c
+++ b/lib/util/debug.c
@@ -236,6 +236,84 @@ static void debug_gpfs_log(int msg_level,
}
#endif /* HAVE_GPFS */
+#define DEBUG_RINGBUF_SIZE (1024 * 1024)
+#define DEBUG_RINGBUF_SIZE_OPT "size="
+
+static char *debug_ringbuf;
+static size_t debug_ringbuf_size;
+static size_t debug_ringbuf_ofs;
+
+/* We ensure in debug_ringbuf_log() that this is always \0 terminated */
+char *debug_get_ringbuf(void)
+{
+ return debug_ringbuf;
+}
+
+/* Return the size of the ringbuf (including a \0 terminator) */
+size_t debug_get_ringbuf_size(void)
+{
+ return debug_ringbuf_size;
+}
+
+static void debug_ringbuf_reload(bool enabled, bool previously_enabled,
+ const char *prog_name, char *option)
+{
+ bool cmp;
+ size_t optlen = strlen(DEBUG_RINGBUF_SIZE_OPT);
+
+ debug_ringbuf_size = DEBUG_RINGBUF_SIZE;
+ debug_ringbuf_ofs = 0;
+
+ SAFE_FREE(debug_ringbuf);
+
+ if (!enabled) {
+ return;
+ }
+
+ if (option != NULL) {
+ cmp = strncmp(option, DEBUG_RINGBUF_SIZE_OPT, optlen);
+ if (cmp == 0) {
+ debug_ringbuf_size = (size_t)strtoull(
+ option + optlen, NULL, 10);
+ }
+ }
+
+ debug_ringbuf = calloc(debug_ringbuf_size, sizeof(char));
+ if (debug_ringbuf == NULL) {
+ return;
+ }
+}
+
+static void debug_ringbuf_log(int msg_level,
+ const char *msg,
+ const char *msg_no_nl)
+{
+ size_t msglen = strlen(msg);
+ size_t allowed_size;
+
+ if (debug_ringbuf == NULL) {
+ return;
+ }
+
+ /* Ensure the buffer is always \0 terminated */
+ allowed_size = debug_ringbuf_size - 1;
+
+ if (msglen > allowed_size) {
+ return;
+ }
+
+ if ((debug_ringbuf_ofs + msglen) < debug_ringbuf_ofs) {
+ return;
+ }
+
+ if ((debug_ringbuf_ofs + msglen) > allowed_size) {
+ debug_ringbuf_ofs = 0;
+ }
+
+ memcpy(debug_ringbuf + debug_ringbuf_ofs, msg, msglen);
+ debug_ringbuf_ofs += msglen;
+}
+
static struct debug_backend {
const char *name;
int log_level;
@@ -278,6 +356,11 @@ static struct debug_backend {
.log = debug_gpfs_log,
},
#endif
+ {
+ .name = "ringbuf",
+ .log = debug_ringbuf_log,
+ .reload = debug_ringbuf_reload,
+ },
};
static struct debug_backend *debug_find_backend(const char *name)
diff --git a/lib/util/debug.h b/lib/util/debug.h
index b50bf502662..43c6aa08c76 100644
--- a/lib/util/debug.h
+++ b/lib/util/debug.h
@@ -287,4 +287,7 @@ typedef void (*debug_callback_fn)(void *private_ptr, int level, const char *msg)
*/
void debug_set_callback(void *private_ptr, debug_callback_fn fn);
+char *debug_get_ringbuf(void);
+size_t debug_get_ringbuf_size(void);
+
#endif /* _SAMBA_DEBUG_H */