From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from elastic.org (elastic.org [96.126.110.187]) by sourceware.org (Postfix) with ESMTPS id 485D93858D28 for ; Fri, 22 Sep 2023 20:36:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 485D93858D28 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=elastic.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=elastic.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=elastic.org ; s=default2; h=Content-Type:MIME-Version:Message-ID:Subject:To:From:Date: Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=zGpd/b1VA9WBhNQE/fcI+7qWGh7FCVDgsRCxvV9p6ZU=; b=VXTHVBiWsSPihZ+Isk9gNxvBYQ dEix/R25Ygvg4zvdeaI3EC7vCBtmHi1qHwl/+HFH1w6nQu5imMN2OZerIj8PcZJwGT2NQgU54HLiv YjIoyDozy4KLUlZ/tzfHI/ml24m6HE3UIFCxU+Fo2daQac02m05DNCMJy0m5nIQDb1D1u5O8q3riN GQFb6tfIOs1jWNailvAcAPjp8eMJ5w8bDqhg/IRCOSOZBZMw/b13hjlLcBrdz6ZWWEnu3Api4XRAT x8Q8C8xmPFTa9+PUqaQ1CthEW9843ljxnRi1+l3EVZzpi/mFlriAEYmELlV/MzsH0c0Ckb6yxYpuo VrSsLrFg==; Received: from vpn-home.elastic.org ([10.0.0.2] helo=elastic.org) by elastic.org with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1qjmsh-0001mr-2q for elfutils-devel@sourceware.org; Fri, 22 Sep 2023 20:36:07 +0000 Received: from fche by elastic.org with local (Exim 4.96) (envelope-from ) id 1qjmsh-000IhU-1Y for elfutils-devel@sourceware.org; Fri, 22 Sep 2023 16:36:07 -0400 Date: Fri, 22 Sep 2023 16:36:07 -0400 From: "Frank Ch. Eigler" To: elfutils-devel@sourceware.org Subject: [PATCH] PR30879: debuginfod intermittent terminate() Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-107.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,SPF_HELO_PASS,SPF_PASS,TXREP,USER_IN_WELCOMELIST,USER_IN_WHITELIST autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Author: Frank Ch. Eigler Date: Fri Sep 22 15:30:51 2023 -0400 PR30879: intermittent debuginfod crash with unhandled exception Code inspection identified two places where sqlite_ps objects were being created/used outside try/catch protection. This patch wraps or replaces them. * configure.ac: Look for glibc backtrace headers. * debuginfod.cxx (scan): New function wrapped by a try/catch loop. (sqlite_checkpoint_pb): Use non-exception-producing sqlite functions. (main, my_terminate_handler): New terminate() handler. diff --git a/configure.ac b/configure.ac index 4b67c84425fa..29ed32feaee6 100644 --- a/configure.ac +++ b/configure.ac @@ -839,6 +839,7 @@ AS_IF([test "x$enable_libdebuginfod" = "xdummy"], [AC_DEFINE([DUMMY_LIBDEBUGINFOD], [1], [Build dummy libdebuginfod])]) AM_CONDITIONAL([LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = "xyes" || test "x$enable_libdebuginfod" = "xdummy"]) AM_CONDITIONAL([DUMMY_LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = "xdummy"]) +AC_CHECK_HEADERS([execinfo.h]) # Look for libmicrohttpd, libarchive, sqlite for debuginfo server # minimum versions as per rhel7. diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx index d72d2ad16960..e53228803bb0 100644 --- a/debuginfod/debuginfod.cxx +++ b/debuginfod/debuginfod.cxx @@ -44,6 +44,12 @@ extern "C" { } #endif +#ifdef HAVE_EXECINFO_H +extern "C" { +#include +} +#endif + extern "C" { #include "printversion.h" #include "system.h" @@ -95,6 +101,7 @@ extern "C" { #include #include #include +#include #include // #include // on rhel7 gcc 4.8, not competent #include @@ -1152,22 +1159,13 @@ struct sqlite_ps struct sqlite_checkpoint_pb: public periodic_barrier { - sqlite_ps ckpt; - + // NB: don't use sqlite_ps since it can throw exceptions during ctor etc. sqlite_checkpoint_pb(unsigned t, unsigned p): - periodic_barrier(t, p), ckpt(db, "periodic wal checkpoint", - "pragma wal_checkpoint(truncate);") {} + periodic_barrier(t, p) { } void periodic_barrier_work() noexcept { - try - { - ckpt.reset().step_ok_done(); - } - catch (const reportable_exception& e) - { - e.report(clog); - } + (void) sqlite3_exec (db, "pragma wal_checkpoint(truncate);", NULL, NULL, NULL); } }; @@ -3714,11 +3712,9 @@ scan_archive_file (const string& rps, const stat_t& st, // The thread that consumes file names off of the scanq. We hold // the persistent sqlite_ps's at this level and delegate file/archive // scanning to other functions. -static void* -thread_main_scanner (void* arg) +static void +scan () { - (void) arg; - // all the prepared statements fit to use, the _f_ set: sqlite_ps ps_f_upsert_buildids (db, "file-buildids-intern", "insert or ignore into " BUILDIDS "_buildids VALUES (NULL, ?);"); sqlite_ps ps_f_upsert_fileparts (db, "file-fileparts-intern", "insert or ignore into " BUILDIDS "_fileparts VALUES (NULL, ?);"); @@ -3845,8 +3841,25 @@ thread_main_scanner (void* arg) inc_metric("thread_work_total","role","scan"); } - add_metric("thread_busy", "role", "scan", -1); +} + + +// Use this function as the thread entry point, so it can catch our +// fleet of exceptions (incl. the sqlite_ps ctors) and report. +static void* +thread_main_scanner (void* arg) +{ + (void) arg; + while (! interrupted) + try + { + scan(); + } + catch (const reportable_exception& e) + { + e.report(cerr); + } return 0; } @@ -4359,6 +4372,20 @@ default_concurrency() // guaranteed >= 1 } +// 30879: Something to help out in case of an uncaught exception. +void my_terminate_handler() +{ +#if defined(__GLIBC__) + void *array[40]; + int size = backtrace (array, 40); + backtrace_symbols_fd (array, size, STDERR_FILENO); +#endif +#if defined(__GLIBCXX__) || defined(__GLIBCPP__) + __gnu_cxx::__verbose_terminate_handler(); +#endif + abort(); +} + int main (int argc, char *argv[]) @@ -4367,6 +4394,8 @@ main (int argc, char *argv[]) (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); (void) textdomain (PACKAGE_TARNAME); + std::set_terminate(& my_terminate_handler); + /* Tell the library which version we are expecting. */ elf_version (EV_CURRENT);