From patchwork Wed May 6 15:29:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2276 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778081444; bh=RGh4Jv/frzWepVxGRLbAdvW+qxejL064rKC1odZq48Y=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=QbJeH6eVwP1vHsIjvqU95KJhjX9SOJbSb1ueACc0Zije/8VF2uKB8WdnMZ1bNKu/4 qcfwL9bMmIllRy7H86GWdq6WSqrzob/E+0vpfi7bYGujPCmY5S5kWHUVuSUq4FzZXq AU7VJqofRlpXkitzlhFIvTkVRn+8YiHrVFuSgEJw= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 5020F6A949 for ; Wed, 6 May 2026 09:30:44 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 1sMiaa37L14Y for ; Wed, 6 May 2026 09:30:44 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778081444; bh=RGh4Jv/frzWepVxGRLbAdvW+qxejL064rKC1odZq48Y=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=QbJeH6eVwP1vHsIjvqU95KJhjX9SOJbSb1ueACc0Zije/8VF2uKB8WdnMZ1bNKu/4 qcfwL9bMmIllRy7H86GWdq6WSqrzob/E+0vpfi7bYGujPCmY5S5kWHUVuSUq4FzZXq AU7VJqofRlpXkitzlhFIvTkVRn+8YiHrVFuSgEJw= Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3D0FB6A937 for ; Wed, 6 May 2026 09:30:44 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778081442; bh=S08rYYeolYID/uOAPh1xQ6wyx8Ie44btB+oc1+fM+38=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ctY17RkiVeZxcprVNFclxFaCP6KWY4ZpeO/ZRzsQu5ViR2hc4weymbOukKbdJm8vw NftU25JuxP9TXERIJUjhSLPolM7oHQeWG0plQXeZ9u3+iFkibZtqmGFRquL/W78BqS MeFxcpmAruLkRyhUfbDNrOQsS6lqx2uRB5cFzAa8= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 465E56A87B; Wed, 6 May 2026 09:30:42 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 2x0jzoX0vM0y; Wed, 6 May 2026 09:30:42 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778081438; bh=Cknkko8D6yJ0RgUzWEwl/teaAFQp3bNUO48uCitajio=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kWrXpq5Hqhdd5eyn31MB8WmYpV1G8x7HYVppwX3zGR74fqYtiV/ma44oMLtZQcZva vvFGpfnHn2gAd236EesoJ6NCwa1vh5wfEF46YDp5NbK2ZCJM8Dcz9fEtbCWa3MnDs0 ZCcCTsE93teK1vZPIF0LyUMXg5wOFdzd8FjpQLs0= Received: from u-boot.org (unknown [174.51.25.52]) by mail.u-boot.org (Postfix) with ESMTPSA id D84FC6A937; Wed, 6 May 2026 09:30:37 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Wed, 6 May 2026 09:29:53 -0600 Message-ID: <20260506153006.529909-5-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260506153006.529909-1-sjg@u-boot.org> References: <20260506153006.529909-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: B3A4QATJMG5P2M3CYX7YQBT2W6IF23X3 X-Message-ID-Hash: B3A4QATJMG5P2M3CYX7YQBT2W6IF23X3 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 4/6] patman: Serialise schema migrations across processes List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Now that PATMAN_DB_DIR lets multiple repos share one database, two patman invocations can race on first launch after a schema bump: both read the old schema_version, both run the same _migrate_to_vN() step, and the second crashes on a duplicate-column ALTER TABLE. Even within a single repo the same race exists; PATMAN_DB_DIR just makes it more visible. Wrap the migration loop in an advisory file lock on .patman.db.lock, acquired with fcntl.flock(LOCK_EX). The first process performs the migration; peers block until it finishes, re-read the (now current) version inside the loop, and exit immediately. The lock fd is independent of the SQLite connection, so the existing close-backup-reopen flow inside the loop still works. Signed-off-by: Simon Glass --- tools/patman/database.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/patman/database.py b/tools/patman/database.py index 2b05a6c4cfe..49b932320b2 100644 --- a/tools/patman/database.py +++ b/tools/patman/database.py @@ -12,6 +12,7 @@ and write some code in migrate_to() to call it. """ from collections import namedtuple, OrderedDict +import fcntl import os import sqlite3 @@ -275,7 +276,20 @@ class Database: # pylint:disable=R0904 Args: dest_version (int): Version to migrate to """ + # Serialise migrations across processes via an advisory lock on a + # sentinel file beside the DB. Without this, two patman processes + # starting against the same out-of-date DB can both decide they + # need to run the next migration step, and the second one crashes + # on a duplicate-column ALTER TABLE + with open(f'{self.db_path}.lock', 'w', encoding='utf-8') as lock_fd: + fcntl.flock(lock_fd, fcntl.LOCK_EX) + self._migrate_locked(dest_version) + + def _migrate_locked(self, dest_version): + """Run the migration loop; caller holds the migration lock""" while True: + # Re-read each iteration: a peer process may have advanced the + # version while we were waiting for the lock version = self.get_schema_version() if version == dest_version: break