summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/common-utils.c
diff options
context:
space:
mode:
authorKrishnan Parthasarathi <kparthas@redhat.com>2014-09-03 11:03:06 +0530
committerKrishnan Parthasarathi <kparthas@redhat.com>2014-09-22 04:08:58 -0700
commit1b53756e50cb9ad5422292d7f4e1e6fe23357222 (patch)
tree30eaf25c1fbc7e359796a86d21897ecd14f4af2a /libglusterfs/src/common-utils.c
parent0cbfe677f361cf49b182748f4b71ded13f6bc988 (diff)
glusterd: Add last successful glusterd lock backtrace
Also, moved the backtrace fetching logic to a separate function. Modified the backtrace fetching logic able to work under memory pressure conditions. Change-Id: Ie38bea425a085770f41831314aeda95595177ece BUG: 1138503 Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-on: http://review.gluster.org/8584 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Jeff Darcy <jdarcy@redhat.com> Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Diffstat (limited to 'libglusterfs/src/common-utils.c')
-rw-r--r--libglusterfs/src/common-utils.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index ec2f07ec994..3a2e557c62b 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -3275,3 +3275,119 @@ gf_set_timestamp (const char *src, const char* dest)
out:
return ret;
}
+
+static void
+gf_backtrace_end (char *buf, size_t frames)
+{
+ size_t pos = 0;
+
+ if (!buf)
+ return;
+
+ pos = strlen (buf);
+
+ frames = min(frames, GF_BACKTRACE_LEN - pos -1);
+
+ if (frames <= 0)
+ return;
+
+ memset (buf+pos, ')', frames);
+ buf[pos+frames] = '\0';
+}
+
+/*Returns bytes written*/
+static int
+gf_backtrace_append (char *buf, size_t pos, char *framestr)
+{
+ if (pos >= GF_BACKTRACE_LEN)
+ return -1;
+ return snprintf (buf+pos, GF_BACKTRACE_LEN-pos, "(--> %s ", framestr);
+}
+
+static int
+gf_backtrace_fillframes (char *buf)
+{
+ void *array[GF_BACKTRACE_FRAME_COUNT];
+ size_t frames = 0;
+ FILE *fp = NULL;
+ char callingfn[GF_BACKTRACE_FRAME_COUNT-2][1024] = {{0},};
+ int ret = -1;
+ int fd = -1;
+ size_t idx = 0;
+ size_t pos = 0;
+ size_t inc = 0;
+ char tmpl[32] = "/tmp/btXXXXXX";
+
+ frames = backtrace (array, GF_BACKTRACE_FRAME_COUNT);
+ if (!frames)
+ return -1;
+
+ fd = gf_mkostemp (tmpl, 0, O_RDWR);
+ if (fd == -1)
+ return -1;
+
+ /*The most recent two frames are the calling function and
+ * gf_backtrace_save, which we can infer.*/
+
+ backtrace_symbols_fd (&array[2], frames-2, fd);
+
+ fp = fdopen (fd, "r");
+ if (!fp) {
+ close (fd);
+ ret = -1;
+ goto out;
+ }
+
+ ret = fseek (fp, 0L, SEEK_SET);
+ if (ret)
+ goto out;
+
+ pos = 0;
+ for (idx = 0; idx < frames - 2; idx++) {
+ ret = fscanf (fp, "%s", callingfn[idx]);
+ if (ret == EOF)
+ break;
+ inc = gf_backtrace_append (buf, pos, callingfn[idx]);
+ if (inc == -1)
+ break;
+ pos += inc;
+ }
+ gf_backtrace_end (buf, idx);
+
+out:
+ if (fp)
+ fclose (fp);
+
+ unlink (tmpl);
+
+ return (idx > 0)? 0: -1;
+
+}
+
+/* Optionally takes @buf to save backtrace. If @buf is NULL, uses the
+ * pre-allocated ctx->btbuf to avoid allocating memory while printing
+ * backtrace.
+ * TODO: This API doesn't provide flexibility in terms of no. of frames
+ * of the backtrace is being saved in the buffer. Deferring fixing it
+ * when there is a real-use for that.*/
+
+char *
+gf_backtrace_save (char *buf)
+{
+ char *bt = NULL;
+
+ if (!buf) {
+ bt = THIS->ctx->btbuf;
+ GF_ASSERT (bt);
+
+ } else {
+ bt = buf;
+
+ }
+
+ if ((0 == gf_backtrace_fillframes (bt)))
+ return bt;
+
+ gf_log (THIS->name, GF_LOG_WARNING, "Failed to save the backtrace.");
+ return NULL;
+}