From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id jLClEsURBmofhToAWB0awg (envelope-from ) for ; Thu, 14 May 2026 14:17:41 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LRfIq4vH; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 39E811E067; Thu, 14 May 2026 14:17:41 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 5AAE71E067 for ; Thu, 14 May 2026 14:17:39 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C3C0C4BCA411 for ; Thu, 14 May 2026 18:17:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C3C0C4BCA411 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LRfIq4vH Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 209944BBC0A4 for ; Thu, 14 May 2026 18:16:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 209944BBC0A4 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 209944BBC0A4 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1778782598; cv=none; b=g3v+3LWwHRjcFSCsU/Uh03ugevl3O2IJwK0RPhTLEhCEC3gxNb6LKU3eqDx3nMUnF5Hehtq6d9hWKAqXkdAlDSbHOgNKlA7CAbeTNL3k2A4VzqmYVImMA+Uw8XkZwvy6WmKWx2sXnn5vm1FawG2u0EnA6JbkkzPH0hciR4ArJmU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1778782598; c=relaxed/simple; bh=d9Eu0MMVUqAMpL9FL67ioZJv/AywLl5j28QFRGs3RzM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Dls4+vqX410HaXCwaOeiFtqpWS+kv/nNwma306i2RBYS2L2sNGmw/cDrHfx1EAimNwrujFOc0uJqp3PCkfd/BJ8+h6JKI2Hx/KKGLW9KdCRRLMW9Tp4zDAvOCmxhmpOx8yN91cV+cNwoJOabEzt3mM8jbDyMmvAZ5eB+xkkS+14= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=LRfIq4vH DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 209944BBC0A4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1778782597; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1bav7v11UN8P7OLSsWzqh9cOdVxjitQUqwzFq0AorBc=; b=LRfIq4vHUYcdnxFLhE02JJwR5QgWvVlN9d6URE2hQh25VRR/YU7ZkdrtWj7DabnhH+5+/d eCs89s8OcJ5ffVQCU6Q9M1yUZyHQowDIqZpokuR7SNu9KAE7j/2xMEYCcckoHiTqTv9LJq nYOTpu+IRMAIdX6pzFH4+yavQkcS7wE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-637-p7LKcg0aO0OH5ZA7F4CL_g-1; Thu, 14 May 2026 14:16:34 -0400 X-MC-Unique: p7LKcg0aO0OH5ZA7F4CL_g-1 X-Mimecast-MFC-AGG-ID: p7LKcg0aO0OH5ZA7F4CL_g_1778782592 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 84DA019560B7; Thu, 14 May 2026 18:16:32 +0000 (UTC) Received: from f44-1.lan (unknown [10.22.80.31]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 86F6C18004A3; Thu, 14 May 2026 18:16:31 +0000 (UTC) From: Kevin Buettner To: gcc-patches@gcc.gnu.org Cc: gdb-patches@sourceware.org, Kevin Buettner Subject: [PATCH] contrib: Make dg-extract-results.py tolerant of unparseable files Date: Thu, 14 May 2026 11:15:03 -0700 Message-ID: <20260514181502.2841511-2-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 92W2SlrkGDx6Hp3WsPfmLwZqHfnwcfIg0xLsdPyWufE_1778782592 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org This commit is for the benefit of GDB, but as the binutils-gdb repository shares the contrib/ directory with GCC, this commit must first be applied to GCC and then copied back to binutils-gdb. When running GDB tests in parallel (make check -j$(nproc)), the consolidated gdb.sum and gdb.log files are produced by contrib/dg-extract-results.py, which merges per-test output files. If any single per-test output file is malformed (e.g., due to a DejaGnu EILSEQ crash, which is how I encountered this problem), the script aborts via self.fatal(). Because this script is invoked via a Makefile command using shell redirection, this causes the top-level output files to be left as empty, zero-byte files, discarding valid results from all other tests. Fix by making the script tolerant of unparseable input files. Wrap each file's parsing in a try/except block. When a file cannot be parsed, emit a warning to stderr and continue processing remaining files. This ensures that crashing tests do not destroy the consolidated output for the entire parallel build. Tested on Fedora 44 using the GCC testsuite (make check-gcc -j$(nproc)). The consolidated results are produced correctly with no regressions. This commit fixes this GDB bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34147 contrib/ChangeLog: * dg-extract-results.py: Show warnings instead of erroring out when encountering an unparseable file. --- contrib/dg-extract-results.py | 44 +++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/contrib/dg-extract-results.py b/contrib/dg-extract-results.py index c7060753500..98b0f4989c9 100644 --- a/contrib/dg-extract-results.py +++ b/contrib/dg-extract-results.py @@ -34,6 +34,16 @@ if sys.version_info >= (3, 0): sys.stdout = io.TextIOWrapper (sys.stdout.buffer, errors = 'surrogateescape') +# Exception raised to skip a file that cannot be parsed. Used when +# a summary or log file is malformed (e.g. due to a DejaGnu EILSEQ +# crash). We will warn about the file and continue processing the +# rest. +class ParseError (Exception): + def __init__ (self, filename, message): + Exception.__init__ (self, filename + ': ' + message) + self.filename = filename + self.message = message + class Named: def __init__ (self, name): self.name = name @@ -205,7 +215,7 @@ class Prog: try: return int (value) except ValueError: - self.fatal (filename, 'expected an integer, got: ' + value) + raise ParseError (filename, 'expected an integer, got: ' + value) # Return a list that represents no test results. def zero_counts (self): @@ -229,7 +239,7 @@ class Prog: while True: line = file.readline() if line == '': - self.fatal (filename, 'could not parse variation list') + raise ParseError (filename, 'could not parse variation list') if line == '\n': break self.known_variations.add (line.strip()) @@ -264,7 +274,7 @@ class Prog: while True: line = file.readline() if line == '': - self.fatal (filename, 'no recognised summary line') + raise ParseError (filename, 'no recognised summary line') if line == end: break @@ -292,7 +302,7 @@ class Prog: match = self.result_re.match (line) if match and (harness or not line.startswith ('WARNING:')): if not harness: - self.fatal (filename, 'saw test result before harness name') + raise ParseError (filename, 'saw test result before harness name') name = match.group (2) # Ugly hack to get the right order for gfortran. if name.startswith ('gfortran.dg/g77/'): @@ -354,7 +364,7 @@ class Prog: found = True break if not found: - self.fatal (filename, 'unknown test result: ' + line[:-1]) + raise ParseError (filename, 'unknown test result: ' + line[:-1]) # Parse an acats run, which uses a different format from dejagnu. # We have just skipped over '=== acats configuration ==='. @@ -367,7 +377,7 @@ class Prog: while True: line = file.readline() if line == '': - self.fatal (filename, 'could not parse acats preamble') + raise ParseError (filename, 'could not parse acats preamble') if line == '\t\t=== acats tests ===\n': break if record: @@ -423,9 +433,9 @@ class Prog: if line.startswith ('Running target '): name = line[len ('Running target '):-1] if not tool: - self.fatal (filename, 'could not parse tool name') + raise ParseError (filename, 'could not parse tool name') if name not in self.known_variations: - self.fatal (filename, 'unknown target: ' + name) + raise ParseError (filename, 'unknown target: ' + name) self.parse_run (filename, file, tool, tool.get_variation (name), num_variations) @@ -474,7 +484,7 @@ class Prog: # individual runs) and parse the version output. if tool and line == '\t\t=== ' + tool.name + ' Summary ===\n': if file.readline() != '\n': - self.fatal (filename, 'expected blank line after summary') + raise ParseError (filename, 'expected blank line after summary') self.parse_final_summary (filename, file) continue @@ -490,7 +500,7 @@ class Prog: # Sanity check to make sure that important text doesn't get # dropped accidentally. if strict and line.strip() != '': - self.fatal (filename, 'unrecognised line: ' + line[:-1]) + raise ParseError (filename, 'unrecognised line: ' + line[:-1]) # Output a segment of text. def output_segment (self, segment): @@ -569,8 +579,18 @@ class Prog: try: # Parse the input files. for filename in self.files: - with safe_open (filename) as file: - self.parse_file (filename, file) + try: + with safe_open (filename) as file: + self.parse_file (filename, file) + except ParseError as e: + # Partial state from this file is intentionally retained. + # This preserves any valid results and diagnostic ERROR + # lines that were parsed before the error, which is + # important for diagnosing problems like DejaGnu crashes. + # The unprocessed remainder of the file is lost. + sys.stderr.write ('warning: skipping ' + e.filename + ': ' + + e.message + + '; results may be incomplete\n') # Decide what to output. if len (self.variations) == 0: -- 2.54.0