From patchwork Tue Sep 15 16:06:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Babanpreet Singh X-Patchwork-Id: 98334 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F167C88E7F for ; Tue, 15 Sep 2026 16:06:46 +0000 (UTC) Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.456.1789488398453294831 for ; Tue, 15 Sep 2026 09:06:38 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=KSEyo7hj; spf=pass (domain: gmail.com, ip: 74.125.227.140, mailfrom: bbnpreetsingh@gmail.com) Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-396ccdaea76so1381089a91.0 for ; Tue, 15 Sep 2026 09:06:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789488398; x=1790093198; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=31ghfM750/FltrKM6hs6zjlTUSqDtyvdkojsG6Pmd4I=; b=KSEyo7hjjwOdNE5/8Bi7XFNMZjsGYecib/IzERAD0eWdSecnaXtDeIe1s2mxAGerLk hJ04WjXH1uDxH9puumcJng5m+l9D0trtueOa9L5JRDGtPbjIG/WCTlxezqQUeXmutNsz i4nM1KIJAHlmDnfzDF4TBZQ9yjpwogG0TB7DWLfymnMLvIzLYHc1BlOTCOmj+/cEgmLk C1bmIdTG10gGL4BtLpboTjSydsjbU1KUrGLZFoXKLiGo+HNJeXx8DfmT+Pv1YA/Ewoar VL1H6Dn1glNHB0TIj/H4jyCC6xQDT4WmZvDlgGxo25K30aQyZWqsMmlhusAVXWhCHIaE Yqew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789488398; x=1790093198; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=31ghfM750/FltrKM6hs6zjlTUSqDtyvdkojsG6Pmd4I=; b=G2PYNs3q+2MwwJ4xAJxfG4dRP43n9yD27NhvFQ3JS0/dz/y3jhkIb4V5TaRsqZrjOq EX2zLsuEV42FsnUX/8HThY1WiQgUfaTsZlXAEY9h9GgDbJaNmJp9vutKeHpRI+2Fm1vt IXPh5XC+Rrcyppe6Jy+NMGn3M3DAO8OjOeuHL2Z4gCR6V7NDhlzbxr8s91ETLmMkRydP UrkmpP/yyq2chvrm69fdxLFyPAwBu0vA513Zh08lK68zv/YQ1OKM2tJtJ4j7oevtdIOe 0LzhHd0pym0WoybkHNO7pG/9+5L6XOiww7dvP7XmoauDndsvxVIvofnrLkprNBEodQ+r KALg== X-Gm-Message-State: AFuF++lC44nu/oht4PRLafbpvwng1TiVSJ47eamPdvlEiLWy93cR0Z2M S04vSQ3e0GffLHAFohRZdWhyBnJmuSYj1b/n0KPkaz2yfM+dOsmmlp/8CCwyQMoq X-Gm-Gg: AYBFou0K9RYfyD4kK02Af9JhOIi3fk0qUTj3KqpuuH02Vl1PhHY4xCfNP/aWXgC4csy VmZMEnnBo8L6makmfkxrvqn4epZBVT2QsDA/Gd0e3UwrJ9T/MWtjCRapD6vFugvInXxEPhIcxqr J9duFkt8AkzbheJkEtwfIeI9/WR9P6ralE0NuuA708WJWz8G+aqEjKNKX2Z8xGIr4RrUJK90dO5 CL79VjdiI28ZBtVmBZJNeOlofB3553G/Pci9lv7Onb3vi+7nhkv7DqLiwx+H9g8NTIBzXXV34rU YTDsApcYAWPAQ2LHQsMh7fxWSf0tRKkuPLOEfqI+5iBK639nBK/jWt1zlj+O+0/sukUOZx/runD 4a27zp8tcrlzXiFR3vW7g+mqCjr2O5p/gZvlSSNFVhVQADzSsW2jge9dEusgp+4u1pcXt9ZtqIP gZhSEkfiwdZO7ej0LdCCwaMGIV2wUct+ka5Cs9ut0VMy1KquKdGDyoKl1+M5OWU1sYesqEuQ8= X-Received: by 2002:a17:90b:3d8e:b0:39d:e1da:81e5 with SMTP id 98e67ed59e1d1-39dfe11c04dmr5141363a91.11.1789488397619; Tue, 15 Sep 2026 09:06:37 -0700 (PDT) Received: from ydev.. ([108.180.130.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfba020d1sm2605678a91.2.2026.09.15.09.06.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 09:06:37 -0700 (PDT) From: Babanpreet Singh To: bitbake-devel@lists.openembedded.org Cc: Richard Purdie , Michael Opdenacker , Babanpreet Singh Subject: [PATCH v2 1/3] prserv/tests: run ScriptTests on a free port with one database Date: Tue, 15 Sep 2026 16:06:31 +0000 Message-ID: <20260915160633.7-2-bbnpreetsingh@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260915160633.7-1-bbnpreetsingh@gmail.com> References: <20260915160633.7-1-bbnpreetsingh@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 15 Sep 2026 16:06:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/bitbake-devel/message/20214 ScriptTests starts bitbake-prserv on the default port (8585) and gives each test its own temporary directory for the database. Anything already listening on 8585 on the test machine stops the daemon from binding. Pick a free port in setUpClass and keep one database directory for the whole class, which is what the oe-selftest prservice test already does for its port. AI-Generated: Uses Claude (claude-fable-5-1) Signed-off-by: Babanpreet Singh --- lib/prserv/tests.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/prserv/tests.py b/lib/prserv/tests.py index df0c00300..f3b2aae45 100644 --- a/lib/prserv/tests.py +++ b/lib/prserv/tests.py @@ -369,20 +369,28 @@ class PRUpstreamTests(PRTestSetup, unittest.TestCase): class ScriptTests(unittest.TestCase): - def setUp(self): - - self.temp_dir = tempfile.TemporaryDirectory(prefix='bb-prserv') - self.addCleanup(self.temp_dir.cleanup) - self.dbfile = os.path.join(self.temp_dir.name, "prtest.sqlite3") + @classmethod + def setUpClass(cls): + cls.temp_dir = tempfile.TemporaryDirectory(prefix='bb-prserv') + cls.dbfile = os.path.join(cls.temp_dir.name, "prtest.sqlite3") + # The server test_1 starts runs until test_2 stops it, so use a + # port nothing else on the machine is listening on + with socket.socket() as s: + s.bind(("0.0.0.0", 0)) + cls.port = str(s.getsockname()[1]) + + @classmethod + def tearDownClass(cls): + cls.temp_dir.cleanup() def test_1_start_bitbake_prserv(self): try: - subprocess.check_call([BIN_DIR / "bitbake-prserv", "--start", "-f", self.dbfile]) + subprocess.check_call([BIN_DIR / "bitbake-prserv", "--start", "-f", self.dbfile, "--port", self.port]) except subprocess.CalledProcessError as e: self.fail("Failed to start bitbake-prserv: %s" % e.returncode) def test_2_stop_bitbake_prserv(self): try: - subprocess.check_call([BIN_DIR / "bitbake-prserv", "--stop"]) + subprocess.check_call([BIN_DIR / "bitbake-prserv", "--stop", "--port", self.port]) except subprocess.CalledProcessError as e: self.fail("Failed to stop bitbake-prserv: %s" % e.returncode) From patchwork Tue Sep 15 16:06:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Babanpreet Singh X-Patchwork-Id: 98332 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1FB76C88E75 for ; Tue, 15 Sep 2026 16:06:46 +0000 (UTC) Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.457.1789488399881877654 for ; Tue, 15 Sep 2026 09:06:39 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=hdOHk/Sd; spf=pass (domain: gmail.com, ip: 74.125.228.12, mailfrom: bbnpreetsingh@gmail.com) Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea4c7a0so316385a12.1 for ; Tue, 15 Sep 2026 09:06:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789488399; x=1790093199; darn=lists.openembedded.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=s6fb5TXbB8qwOkzgXy94K5y4VFM4yM83CN02QI5uWhA=; b=hdOHk/Sd2PCXNHPMMP8kuDP+N+7g+//cahxg+KoxNYrGNd8c61SheoHywb8/Bg6NnG zKSqd/MJimREf/EK2FV0EpKnOc89c4En/9qbP+V7AWLceHE48fU/KNDg5K5mZDwYd+TK GMEjh7DrDvxE+lvFIZuWz1+/67B8e9GJBGbc/AP3dl2dkMYCjgebIxtwXcn/0fAWvsGr 4jbVsVxTXROItytost8lyBSTR00hiNGZd+OYBzS3vFkpUFpwaajtE8hlvESYmpLh6ZQ9 NU/p3Opbylt3mFETGZbpzw2alWsQaq/GGcJPrwT79iMxqBjuvV+6odpY4Losf4LDKTnH dzHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789488399; x=1790093199; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=s6fb5TXbB8qwOkzgXy94K5y4VFM4yM83CN02QI5uWhA=; b=Z2EBXVNka66zK6Wa9GiwlViVWG9NI5BXvdlKWgcbeRL6ed9z79jNXK1+aVJgIVetP3 yW6xuA0sz2tVNUdM2IVG/CDpfy+v4aUNVZcBn/Vq3gbpBvWwjPdJnJt+7RorGuaM576l 0xwl5yeu1vybEXXIWDZccFX8k1dzfAuNwShhUBSP2CMJcrTXYro7hqPqN4JZU7CuG9sI L6zIYxfPUpF2AF+19HD5rE4K8jbOP2uwAnG2QlIimE779G6jDOrTdgKSoiNLBIx+5Fzp KRhCgg43+qYmtrpiOk5dMFUXRhigaD+H+BW4Zmm1oOshKn83DO3Bc05ezZVD/YgKa2ZO vDjA== X-Gm-Message-State: AFuF++kO5gZ9W2UeEDqQOzgz6cPLR/6pjeubCHU/ZcWcB2KAx1hv3TFl KWmHNkLQBU1h7FOqXcPB7IFt09XmY3bxcGMocPPuwgzMzs155tWUb99d70KueULAa7w= X-Gm-Gg: AYBFou2JbJygEsNs38SGXf3hi4HWg+pw2CdYaExyrT24F9nqFu5WmKqB1WcxWYE4xt7 VMLk68ff5I061LHUgqCNGa/Y1JoXKIg9WB7GFrx439smyRSGJ+rwUc+fGmiotuT26ls7BvPwewd mD5xRUynfSa34jkClsExu99oYkxGxDf4QtLPT8LWestQMOntqlt5/4LvwzACJ3Lqp9Bt6+vMXB4 5zVRdKzN4yhlBQMWSIHtHWoQnTRAyutNWNv3q257ulJeajDRS7UsJi+pl9HS5SINgL3cYfp9lGf vNec07lBbzxXKQAvfue8ciIL67OI0puS/ff0fA4REPzGJhVKQ+I5Ogf2rvORlkB1z7MQ5CcqH5R poGAir1xajtfSf+o7ZhHootVA5eLEsSIoFuRcbDc9weJ7uSWLRE3KjkjODzyc3xyzUXp7c+ctc3 L1wr81dZd5EsFlali1trZ1euMf/r/7qsM/NAHBlOhvOif6BOEM7Wt6xWQPy7zPQSaRMEm1psKSU +MBN52gCw== X-Received: by 2002:a17:90b:3881:b0:398:d6e8:f84e with SMTP id 98e67ed59e1d1-39e10cedc66mr2749005a91.9.1789488398988; Tue, 15 Sep 2026 09:06:38 -0700 (PDT) Received: from ydev.. ([108.180.130.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfba020d1sm2605678a91.2.2026.09.15.09.06.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 09:06:37 -0700 (PDT) From: Babanpreet Singh To: bitbake-devel@lists.openembedded.org Cc: Richard Purdie , Michael Opdenacker , Babanpreet Singh Subject: [PATCH v2 2/3] prserv: make --start fail when the server does not come up Date: Tue, 15 Sep 2026 16:06:32 +0000 Message-ID: <20260915160633.7-3-bbnpreetsingh@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260915160633.7-1-bbnpreetsingh@gmail.com> References: <20260915160633.7-1-bbnpreetsingh@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 15 Sep 2026 16:06:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/bitbake-devel/message/20215 Make `prserv --start` fail when the server can’t start, and clean up stale pidfiles on failure. AI-Generated: Uses Claude (claude-fable-5-1) Signed-off-by: Babanpreet Singh --- lib/prserv/serv.py | 53 +++++++++++++++++++++++++++++++++++++++------ lib/prserv/tests.py | 14 ++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/lib/prserv/serv.py b/lib/prserv/serv.py index e17588630..6aba1c3e0 100644 --- a/lib/prserv/serv.py +++ b/lib/prserv/serv.py @@ -205,12 +205,13 @@ class PRServerClient(bb.asyncrpc.AsyncServerConnection): return {"readonly": self.server.read_only} class PRServer(bb.asyncrpc.AsyncServer): - def __init__(self, dbfile, read_only=False, upstream=None): + def __init__(self, dbfile, read_only=False, upstream=None, on_ready=None): super().__init__(logger) self.dbfile = dbfile self.table = None self.read_only = read_only self.upstream = upstream + self.on_ready = on_ready def accept_client(self, socket): return PRServerClient(socket, self) @@ -226,6 +227,9 @@ class PRServer(bb.asyncrpc.AsyncServer): if self.upstream is not None: self.logger.info("And upstream PRServer: %s " % (self.upstream)) + if self.on_ready is not None: + self.on_ready() + return tasks async def stop(self): @@ -253,16 +257,27 @@ class PRServSingleton(object): def run_as_daemon(func, pidfile, logfile): """ See Advanced Programming in the UNIX, Sec 13.3 + + func runs in the daemon and is passed a callable to invoke once it is + ready to serve. Return the daemon's pid when that happens; raise + RuntimeError with the daemon's error if it fails first. """ + readfd, writefd = os.pipe() try: pid = os.fork() if pid > 0: + os.close(writefd) os.waitpid(pid, 0) + with os.fdopen(readfd) as f: + report = f.read() + if report != "ready": + raise RuntimeError(report or "daemon exited before it was ready") #parent return instead of exit to give control return pid except OSError as e: raise Exception("%s [%d]" % (e.strerror, e.errno)) + os.close(readfd) os.setsid() """ fork again to make sure the daemon is not session leader, @@ -316,9 +331,27 @@ def run_as_daemon(func, pidfile, logfile): with open(pidfile, "w") as pf: pf.write("%s\n" % pid) - func() - os.remove(pidfile) - os._exit(0) + def ready(): + nonlocal writefd + os.write(writefd, b"ready") + os.close(writefd) + writefd = None + + ret = 0 + try: + func(ready) + except Exception as e: + import traceback + traceback.print_exc() + if writefd is not None: + os.write(writefd, str(e).encode()) + ret = 1 + try: + os.remove(pidfile) + except FileNotFoundError: + # --stop may have removed it already + pass + os._exit(ret) def start_daemon(dbfile, host, port, logfile, read_only=False, upstream=None): ip = socket.gethostbyname(host) @@ -335,12 +368,18 @@ def start_daemon(dbfile, host, port, logfile, read_only=False, upstream=None): return 1 dbfile = os.path.abspath(dbfile) - def daemon_main(): - server = PRServer(dbfile, read_only=read_only, upstream=upstream) + logfile = os.path.abspath(logfile) + def daemon_main(ready): + server = PRServer(dbfile, read_only=read_only, upstream=upstream, on_ready=ready) server.start_tcp_server(ip, port) server.serve_forever() - run_as_daemon(daemon_main, pidfile, os.path.abspath(logfile)) + try: + run_as_daemon(daemon_main, pidfile, logfile) + except RuntimeError as e: + sys.stderr.write("Failed to start PRServer on %s:%s: %s\nSee %s for details.\n" + % (ip, port, e, logfile)) + return 1 return 0 def stop_daemon(host, port): diff --git a/lib/prserv/tests.py b/lib/prserv/tests.py index f3b2aae45..f1e4f12c8 100644 --- a/lib/prserv/tests.py +++ b/lib/prserv/tests.py @@ -7,6 +7,7 @@ from . import create_server, create_client, increase_revision, revision_greater, revision_smaller, _revision_greater_or_equal import prserv.db as db +from prserv.serv import PIDPREFIX from bb.asyncrpc import InvokeError import logging import os @@ -383,6 +384,19 @@ class ScriptTests(unittest.TestCase): def tearDownClass(cls): cls.temp_dir.cleanup() + def test_0_start_bitbake_prserv_port_in_use(self): + with socket.socket() as s: + s.bind(("0.0.0.0", 0)) + s.listen() + port = str(s.getsockname()[1]) + result = subprocess.run([BIN_DIR / "bitbake-prserv", "--start", "-f", self.dbfile, "--port", port], + capture_output=True, text=True) + self.assertNotEqual(result.returncode, 0, + "--start reported success with the port in use") + self.assertIn("Failed to start PRServer", result.stderr) + self.assertFalse(os.path.exists(PIDPREFIX % ("0.0.0.0", port)), + "pidfile left behind by a server that never came up") + def test_1_start_bitbake_prserv(self): try: subprocess.check_call([BIN_DIR / "bitbake-prserv", "--start", "-f", self.dbfile, "--port", self.port]) From patchwork Tue Sep 15 16:06:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Babanpreet Singh X-Patchwork-Id: 98333 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64158C982C7 for ; Tue, 15 Sep 2026 16:06:46 +0000 (UTC) Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.458.1789488402070815541 for ; Tue, 15 Sep 2026 09:06:42 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20251104 header.b=XrP8TsJg; spf=pass (domain: gmail.com, ip: 74.125.228.12, mailfrom: bbnpreetsingh@gmail.com) Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc1cea34ef4so418418a12.3 for ; Tue, 15 Sep 2026 09:06:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789488401; x=1790093201; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4aOj/tv/oPKW7Gvz2ecPaDtA6tIX97TR4dA8ifBEBN0=; b=XrP8TsJgaO+fFbnBIB1mqGDBQRuwsfCsMy51S9x3ewtQaQu7YOUfwvRvaLgGJ4Cla2 xnmkIw8t80VFgeTzKtiXxBn8Je00Qdr+ce2a1ryd0bMyF9b+/ieZp+LhSeFZP+j/lsEO KzwgWTuHjclj45YwKjA1u5mVqIFF+Y4/pLiAIvqqGXHjmDQprP7ecmGzsN9H0AxhUdpu +TlbEzlXRieLfG/jFu5Dj9TCkzwI1QNRhbOmje0X7OIOxKlclchhE5U5l+wcktHIJdmF dr6RyQeWIUA4JeoDNjg9vUHXBPNbscY9UyYPAT1qH8WKeuuxN2BDf4tx7QYs6x6d1+Ew CASg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789488401; x=1790093201; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=4aOj/tv/oPKW7Gvz2ecPaDtA6tIX97TR4dA8ifBEBN0=; b=aeCGO0kd7hgfPtqHKdpmajF7mv9kBMI0VodQ0n8rKmrW7DEjQKsoD4Yl06QwOKX6eW l9ms3wUiOkdOvN2A4YEcSIdgqmbPFUi3ZMQrJachGTYK9TXaRtPlHa+5e+mrF+9YYM0N +387WSHjeldX64WL5Yo+EGD9EgXhONXzPoH1DSzdhxK7ktWdIYwhDxHYA66tZOROKiqx xQgUA3fK2Dl/Lr1og6WovzrPTRSVNjx0Vh326waE78EWZBCNM0yG2tPxyv1AVn1EY8HH pY+kZupQO7rcmez5AIUsO9u3mFi9Z6CXqJiLUD35S3hFWDDIoPr+yQT6veZVtLJsaE05 r0ow== X-Gm-Message-State: AFuF++noBjzVv773SCC/FxALc7E7yv2Vetrs62xoLyu/rBSd6RUMiSSJ hcaTNdAWSfTvp+FYXpf8/pcc12HBw3r6NNUpQJZ+IxbFuMIA//nQaiEHmDhfXe2cZTE= X-Gm-Gg: AYBFou1cLrFDdHJg2SK+rhfh6y6MkFln0alLPNT5qrDyazXoSjylCK0MFoyai903o0Q H13qKvPlCV6TgHLbfLply4/D8bPL1KoZIhqvJUYGW6UF0k8gfyMOi7aydLTjea2Kwb9plAudm4w 7x8/QNJvPjGlajuZKjEbpv+kqpRX9GswsCVsu3uBrotw3DLckO+A40BR/TE3DlKSCkVVnuqxdv2 yI54u0nhE2j2MXNXEkbB1eBdwS8rTWtUUkBhb5ORmjjWrS+Y/ePc/AJoq9PLCqTM7Ub5NTJpjzv M+vtkmNlrNZHicUvJGk7tldIFIDRjseRoCZrZLOfSzGsuZY511YMomAoICyH9ml/U0IWhJV3Be4 PQ1Ui2jzIEa1FC7wxAU50Ss5dRwrTF78MuXA8/Q8Kl32sHSAaFERy1MKOUuad7eilSxNkYsFCNO pmujKmAfoEpcWgPGEcZyKFx86T3Qd5+68u0dLDmQTvIapGrQWSPqLAgRnbYLfZQhvTkuSJ0gk= X-Received: by 2002:a17:90a:1048:b0:39e:1329:7816 with SMTP id 98e67ed59e1d1-39e13298c84mr1520403a91.15.1789488401382; Tue, 15 Sep 2026 09:06:41 -0700 (PDT) Received: from ydev.. ([108.180.130.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfba020d1sm2605678a91.2.2026.09.15.09.06.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 09:06:40 -0700 (PDT) From: Babanpreet Singh To: bitbake-devel@lists.openembedded.org Cc: Richard Purdie , Michael Opdenacker , Babanpreet Singh Subject: [PATCH v2 3/3] prserv: add --status to list running servers Date: Tue, 15 Sep 2026 16:06:33 +0000 Message-ID: <20260915160633.7-4-bbnpreetsingh@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260915160633.7-1-bbnpreetsingh@gmail.com> References: <20260915160633.7-1-bbnpreetsingh@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 15 Sep 2026 16:06:46 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/bitbake-devel/message/20216 Add `prserv --status` to report running servers and stale pidfiles, with lifecycle tests for both running and stopped states. [YOCTO #10865] AI-Generated: Uses Claude (claude-fable-5-1) Signed-off-by: Babanpreet Singh --- bin/bitbake-prserv | 7 +++++++ lib/prserv/serv.py | 23 +++++++++++++++++++++++ lib/prserv/tests.py | 18 +++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/bin/bitbake-prserv b/bin/bitbake-prserv index e666fef06..5775f47fb 100755 --- a/bin/bitbake-prserv +++ b/bin/bitbake-prserv @@ -64,6 +64,11 @@ def main(): action="store_true", help="stop daemon", ) + parser.add_argument( + "--status", + action="store_true", + help="list PR servers running on this machine", + ) parser.add_argument( "--host", help="ip address to bind", @@ -102,6 +107,8 @@ def main(): ) elif args.stop: ret=prserv.serv.stop_daemon(args.host, args.port) + elif args.status: + ret=prserv.serv.status_daemon() else: ret=parser.print_help() return ret diff --git a/lib/prserv/serv.py b/lib/prserv/serv.py index 6aba1c3e0..a49faeb4a 100644 --- a/lib/prserv/serv.py +++ b/lib/prserv/serv.py @@ -427,6 +427,29 @@ def stop_daemon(host, port): return 0 +def status_daemon(): + import glob + running = 0 + for pidfile in sorted(glob.glob(PIDPREFIX % ("*", "*"))): + root, _ = os.path.splitext(os.path.basename(pidfile)) + parts = root.split("_") + ip, port = "_".join(parts[1:-1]), parts[-1] + try: + with open(pidfile) as pf: + pid = int(pf.readline().strip()) + except (IOError, ValueError): + sys.stderr.write("Ignoring unreadable pidfile %s\n" % pidfile) + continue + if is_running(pid): + print("PRServer running at %s:%s (pid %s)" % (ip, port, pid)) + running += 1 + else: + print("Stale pidfile %s (pid %s not running)" % (pidfile, pid)) + if not running: + print("No PRServer running.") + return 1 + return 0 + def is_running(pid): try: os.kill(pid, 0) diff --git a/lib/prserv/tests.py b/lib/prserv/tests.py index f1e4f12c8..8b78e2496 100644 --- a/lib/prserv/tests.py +++ b/lib/prserv/tests.py @@ -403,8 +403,24 @@ class ScriptTests(unittest.TestCase): except subprocess.CalledProcessError as e: self.fail("Failed to start bitbake-prserv: %s" % e.returncode) - def test_2_stop_bitbake_prserv(self): + def test_2_status_bitbake_prserv(self): + result = subprocess.run([BIN_DIR / "bitbake-prserv", "--status"], + capture_output=True, text=True) + self.assertEqual(result.returncode, 0, + "Expected a running PRServer: %s" % result.stdout) + self.assertIn(":%s (pid " % self.port, result.stdout) + + def test_3_stop_bitbake_prserv(self): try: subprocess.check_call([BIN_DIR / "bitbake-prserv", "--stop", "--port", self.port]) except subprocess.CalledProcessError as e: self.fail("Failed to stop bitbake-prserv: %s" % e.returncode) + + def test_4_status_stopped_bitbake_prserv(self): + result = subprocess.run([BIN_DIR / "bitbake-prserv", "--status"], + capture_output=True, text=True) + self.assertNotIn(":%s (pid " % self.port, result.stdout) + # Servers unrelated to this test may be running on the machine + if "PRServer running at" not in result.stdout: + self.assertEqual(result.returncode, 1, + "Expected no running PRServer: %s" % result.stdout)