diff options
author | Krishnan Parthasarathi <kparthas@redhat.com> | 2014-09-03 11:03:06 +0530 |
---|---|---|
committer | Krishnan Parthasarathi <kparthas@redhat.com> | 2014-09-22 04:08:58 -0700 |
commit | 1b53756e50cb9ad5422292d7f4e1e6fe23357222 (patch) | |
tree | 30eaf25c1fbc7e359796a86d21897ecd14f4af2a /libglusterfs/src/common-utils.c | |
parent | 0cbfe677f361cf49b182748f4b71ded13f6bc988 (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.c | 116 |
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; +} |