From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 8390A1FF09B for ; Mon, 09 Nov 2026 15:25:22 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 3B8292158E; Mon, 09 Nov 2026 15:25:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794234307; x=1794839107; darn=lists.proxmox.com; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Jd91v97ZpJI7RZVfQNtDh7DwnpbnHvn+nEGqHBZ5+TE=; b=i44+PN7Gy9UT7rfqPV5SLey2tfFbiZApwBvfU3DeiRsGX6x+Yu+GqAPHRzv8upKGNl PORH/e3DWiPleLwG5lDroZIH7Wm9G8mNEG6Syp75h3AXQjxok1XpXfPj+QL0nCGZyyG9 vlLKQi3OeyOTxoW2AhrdxakfrNti3/9pTacQm+7OB9pN/sn6KjRPx56gJTRquJSmgbyR 5FB6S6pECLHfvCN8K3WxhMV/rL17LyG6P8kcLqAFdTpJM/9l1YSHO+DnrWhU7bO3FyJ+ yXgN2fgJKcixGtxxyOwKympdWzg4fjqAt720MVMelF32jTYd/c6NP9wbsME0z3yfQj5b rU0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794234307; x=1794839107; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=Jd91v97ZpJI7RZVfQNtDh7DwnpbnHvn+nEGqHBZ5+TE=; b=Q+UHlDNt+jspmHMF4CxaxCWoGKH5OpJANpCBX6xcRMLvh74QYXScwhPyLACFmtFTFz FgX1CNuNivjDXHb7/twIHOffXkF44sMULsM1R4i8oAE58oqmD5z/smsUxEBrzDPo8nxx EO3L2kGM/NTihGjK8LKjIyLeR1t+cTwugj53bSHVVcw/qkeTAYIvDGjecQO4A8rA5wYr 9nKwnLykgeeypG4fYLlSJH2jsZ3nP52687frqlryDO2ZmUQMhcRqy4feO5fRLQ9OLOrt uF4nxbwD1hLdMHsPa8EyNrpEsMAsCQ10qdiTjc7OWFeStVv64qGn1GyX/GFofnRQ81ST U9Ag== X-Gm-Message-State: APuU4Z+QgSiKY2IF+FD7N3ZtkSE6ooFGETzyDgifKmv5a2XhdRrJLWpB W/S6rToEHHovjJbzmykX00ib7MR5un+OcyrhCdP4ZWI4N/NCqifzaINCojDqPCr8 X-Gm-Gg: AYBFou0I5Vy+B+E2x5faBH17JJ3xUiIDCqCeF7FVaShx5F9NwqWxLp3pYuZBrH8RSoi HXZOH4bG4RkWNT/oALWbsYTFiFCs6VlRUjF2C6VHt07VN0Zaoq3sne07p7UuuypjfL04uroGDIp ptTLnK10PoXIKJIyhtAaGChLNWCw6k0Nvc/yEMvo/CgiarHBtUNBWyuAW+B8UcQVWVaN2lv5nRZ w4LtOx7Wf6IDC0FKDmB0rlXqjeFdm0TOyC85tiDFflPPhNHWTucaT1pySJliclbuNVHgPNgbFDA h20QGKkBSyQrcE7lnFiGhVu4Ka3tbAQk0gYcmAba27YWkh7OuqLi/RCFQ5X2Z6PA+n6bYPwk01d r9zZh7Dlamt8gzymOXHk+MSIJmZGJbseut/9vawMp0ggqNoTIeCmulN0Piloj6SrnPVvK5fovYj g//WYOR48qwJzrVsmawgGsi46ylWwHG4nkecaHDCwkbcw5E/CWaaUbE2amwlFCQh0lEcJPTxuni c4JKqJUoHyspQ4YQ5XrX+xSCCwIQYJ08TsdnzVChLEP1yyDqO/v0yXzjc3FrsJSxNNtUiTsSGzS M8K2ORiZ/F5OFrFTXDq/bO5sWNIsJvLdaMCY5eXm2lp0ROmjL9jz1r2LdfJHtxRjoBfYFGeQIx6 RytnHaLeeJAAmP+Z0EfccbO9NwW2ow3UWpvBk6QAdu1rJUw== X-Received: by 2002:a05:6122:2386:b0:5ea:bdea:320e with SMTP id 71dfb90a1353d-5ece725c058mr1588795e0c.18.1794234307197; Mon, 09 Nov 2026 06:25:07 -0800 (PST) From: Lucas Barros To: pve-devel@lists.proxmox.com Subject: [PATCH common] fix #8288: file: read first line: treat ESRCH like a missing file Date: Mon, 9 Nov 2026 11:25:01 -0300 Message-ID: <20261109142501.23212-1-lucasbarros.kam@gmail.com> X-Mailer: git-send-email 2.50.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.150 Adjusted score from AWL reputation of From: address DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain DKIM_VALID_EF -0.1 Message has a valid DKIM or DK signature from envelope-from domain DMARC_PASS -0.1 DMARC pass policy FREEMAIL_FROM 0.001 Sender email is commonly abused enduser mail provider RCVD_IN_DNSWL_NONE -0.0001 Sender listed at https://www.dnswl.org/, no trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: UMQDDLTNX5ZHVSZKBP6TDV4LGAYNW64Z X-Message-ID-Hash: UMQDDLTNX5ZHVSZKBP6TDV4LGAYNW64Z X-MailFrom: lucasbarros.kam@gmail.com 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 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Opening a file below /proc// can fail with ESRCH instead of ENOENT when the process exits and gets reaped while the path is looked up, as the permission check on the /proc/ directory then no longer finds the task. file_read_first_line() only treats ENOENT as "does not exist" and dies otherwise. This is hit by check_process_running(), which polls /proc//stat via read_proc_pid_stat(). On boot, startall uses it to wait for the start workers of each startup order, outside of any eval, so a worker exiting at the wrong moment aborts startall: pve-guests.service fails and guests of later startup orders are not started at all. A process that is gone is simply not running, so return undef for ESRCH as well, just like for ENOENT. ESRCH is only returned by procfs here, so other files are not affected. Signed-off-by: Lucas Barros --- Reproduced on a PVE 9 node (kernel 7.0.14-28-pve, libpve-common-perl 9.2.8, 2 vCPUs) with a small script: one process forks short-lived children and reaps them, another polls each child with PVE::ProcFSTools::check_process_running(), like startall does with its start workers. 60 seconds each: before (installed libpve-common-perl): check_process_running polls: 414951, died: 58 58x file '/proc//stat' exists but open for reading failed - No such process after (with this patch): check_process_running polls: 389918, died: 0 stopall and migrateall poll their workers with check_process_running() as well. In the same kind of loop, reading an already opened /proc//stat can also fail with ESRCH, but that already ends up as undef, as the result of the read is not checked for errors. Only file_read_first_line() is changed, as that is what the /proc helpers use. file_read_last_line() has the same ENOENT check, I can extend it there as well for consistency if preferred. An alternative would be to handle this in read_proc_pid_stat() only, but the other /proc// readers have the same race. The test suite passes before and after ('make check', 347 vs. 349 ok), the new test in file-test.pl fails without the change. proxmox-perltidy reports no changes. This patch was prepared with the help of an LLM based coding assistant; I reviewed the change and ran the tests mentioned above myself. src/PVE/File.pm | 4 +++- test/file-test.pl | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/PVE/File.pm b/src/PVE/File.pm index 7d0f7ab..8162552 100644 --- a/src/PVE/File.pm +++ b/src/PVE/File.pm @@ -118,7 +118,9 @@ sub file_copy($filename, $dst, $max = undef, $perm = undef) { sub file_read_first_line($filename) { my $fh = IO::File->new($filename, "r"); if (!$fh) { - return undef if $! == POSIX::ENOENT; + # opening a file below /proc// fails with ESRCH instead of ENOENT if the process + # exits during the path lookup, treat it the same as a file that does not exist + return undef if $! == POSIX::ENOENT || $! == POSIX::ESRCH; die "file '$filename' exists but open for reading failed - $!\n"; } my $res = <$fh>; diff --git a/test/file-test.pl b/test/file-test.pl index 6c55105..ebba6c9 100755 --- a/test/file-test.pl +++ b/test/file-test.pl @@ -10,6 +10,8 @@ use PVE::File; use Encode; use File::Path qw(remove_tree); +use POSIX (); +use Test::MockModule; use Test::More; # TODO: @@ -63,6 +65,20 @@ is_deeply( "simple write-read-compare test with wide-characters", ); +# a file below /proc// of a process that is just exiting can fail to open with ESRCH +{ + my $io_file = Test::MockModule->new('IO::File'); + $io_file->redefine( + new => sub { + $! = POSIX::ESRCH; + return undef; + }, + ); + my $res = eval { PVE::File::file_read_first_line("/proc/1/stat") }; + is($@, '', "ESRCH on open does not die"); + is($res, undef, "ESRCH on open is treated like a file that does not exist"); +} + done_testing(); remove_tree($test_dir); -- 2.47.3