From patchwork Wed Aug 24 08:44:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marius Vlad X-Patchwork-Id: 9297173 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5E93B607F0 for ; Wed, 24 Aug 2016 08:44:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 51F0328E93 for ; Wed, 24 Aug 2016 08:44:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4688728E95; Wed, 24 Aug 2016 08:44:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B1C3528E93 for ; Wed, 24 Aug 2016 08:44:19 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2CA036E80A; Wed, 24 Aug 2016 08:44:19 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTPS id 47C276E80A for ; Wed, 24 Aug 2016 08:44:18 +0000 (UTC) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP; 24 Aug 2016 01:44:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,570,1464678000"; d="scan'208";a="752838647" Received: from mcvlad-wk.rb.intel.com ([10.237.105.57]) by FMSMGA003.fm.intel.com with ESMTP; 24 Aug 2016 01:44:16 -0700 From: Marius Vlad To: intel-gfx@lists.freedesktop.org Date: Wed, 24 Aug 2016 11:44:07 +0300 Message-Id: <1472028247-8210-1-git-send-email-marius.c.vlad@intel.com> X-Mailer: git-send-email 2.8.1 In-Reply-To: <20160823085531.GC20834@nuc-i3427.alporthouse.com> References: <20160823085531.GC20834@nuc-i3427.alporthouse.com> Subject: [Intel-gfx] [PATCH i-g-t v3] lib/igt_core: Print stacktrace when receiving one of the crash signals. X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP While at it add SIGFPE as a crash signal. v3: Remove calls to igt_assert_eq() as these are not async-safe. As one user of this method remove the function pointer and recursive call. (Chris Wilson) v2: Added some helpers to avoid printf() inside a signal handler. (Chris Wilson) --- lib/igt_core.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 2 deletions(-) diff --git a/lib/igt_core.c b/lib/igt_core.c index 801f02f..7e5bf76 100644 --- a/lib/igt_core.c +++ b/lib/igt_core.c @@ -1098,6 +1098,179 @@ static void print_backtrace(void) (unsigned int) off); } } + +static const char hex[] = "0123456789abcdef"; + +static void +xputch(int c) +{ + write(STDERR_FILENO, (const void *) &c, 1); +} + +static int +xpow(int base, int pow) +{ + int i, r = 1; + + for (i = 0; i < pow; i++) + r *= base; + + return r; +} + +static void +printnum(unsigned long long num, unsigned base) +{ + int i = 0; + unsigned long long __num; + + /* determine from where we should start dividing */ + do { + __num /= base; + i++; + } while (__num); + + while (i--) + xputch(hex[num / xpow(base, i) % base]); +} + +static size_t +xstrlcpy(char *dst, const char *src, size_t size) +{ + char *dst_in; + + dst_in = dst; + if (size > 0) { + while (--size > 0 && *src != '\0') + *dst++ = *src++; + *dst = '\0'; + } + + return dst - dst_in; +} + +static void +xprintfmt(const char *fmt, va_list ap) +{ + const char *p; + int ch, base; + unsigned long long num; + + while (1) { + while ((ch = *(unsigned char *) fmt++) != '%') { + if (ch == '\0') { + return; + } + xputch(ch); + } + + ch = *(unsigned char *) fmt++; + switch (ch) { + /* character */ + case 'c': + xputch(va_arg(ap, int)); + break; + /* string */ + case 's': + if ((p = va_arg(ap, char *)) == NULL) { + p = "(null)"; + } + + for (; (ch = *p++) != '\0';) { + if (ch < ' ' || ch > '~') { + xputch('?'); + } else { + xputch(ch); + } + } + break; + /* (signed) decimal */ + case 'd': + num = va_arg(ap, int); + if ((long long) num < 0) { + xputch('-'); + num = -(long long) num; + } + base = 10; + goto number; + /* unsigned decimal */ + case 'u': + num = va_arg(ap, unsigned int); + base = 10; + goto number; + /* (unsigned) hexadecimal */ + case 'x': + num = va_arg(ap, unsigned int); + base = 16; +number: + printnum(num, base); + break; + + /* The following are not implemented */ + + /* width field */ + case '1': case '2': + case '3': case '4': + case '5': case '6': + case '7': case '8': + case '9': + case '.': case '#': + /* long */ + case 'l': + /* octal */ + case 'o': + /* pointer */ + case 'p': + /* float */ + case 'f': + abort(); + /* escaped '%' character */ + case '%': + xputch(ch); + break; + /* unrecognized escape sequence - just print it literally */ + default: + xputch('%'); + for (fmt--; fmt[-1] != '%'; fmt--) + ; /* do nothing */ + break; + } + } +} + +/* async-safe printf */ +static void +xprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + xprintfmt(fmt, ap); + va_end(ap); +} + +static void print_backtrace_sig_safe(void) +{ + unw_cursor_t cursor; + unw_context_t uc; + int stack_num = 0; + + write(STDERR_FILENO, "Stack trace: \n", 15); + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + while (unw_step(&cursor) > 0) { + char name[255]; + unw_word_t off; + + if (unw_get_proc_name(&cursor, name, 255, &off) < 0) + xstrlcpy(name, "", 9); + + xprintf(" #%d [%s+0x%x]\n", stack_num++, name, + (unsigned int) off); + + } +} #endif void __igt_fail_assert(const char *domain, const char *file, const int line, @@ -1482,7 +1655,8 @@ static bool exit_handler_disabled; #define SILENT(x) { x, NULL, 0 } static const struct { int number; const char *name; size_t name_len; } handled_signals[] = { SILENT(SIGINT), SILENT(SIGHUP), SILENT(SIGTERM), SILENT(SIGQUIT), - SILENT(SIGPIPE), SIGDEF(SIGABRT), SIGDEF(SIGSEGV), SIGDEF(SIGBUS) }; + SILENT(SIGPIPE), SIGDEF(SIGABRT), SIGDEF(SIGSEGV), SIGDEF(SIGBUS), + SIGDEF(SIGFPE) }; #undef SILENT #undef SIGDEF @@ -1542,6 +1716,7 @@ static bool crash_signal(int sig) switch (sig) { case SIGILL: case SIGBUS: + case SIGFPE: case SIGSEGV: return true; default: @@ -1571,7 +1746,7 @@ static void fatal_sig_handler(int sig) igt_exitcode = 128 + sig; failed_one = true; - + print_backtrace_sig_safe(); exit_subtest("CRASH"); } break;