fix(resource_plan): take last two lscpu fields, not [1]/[2] (#332 review)

JustVugg caught a regression by running the PR: the code asked
`lscpu -p=CPU,Core,Socket` and read fields[1]/fields[2], but the comment's
claim was inverted -- `lscpu -p=<list>` emits EXACTLY the requested columns
(no CPU prefix), while bare `lscpu -p` prepends CPU.

On machines where the requested list is short or lscpu collapses to two
columns, every line was skipped by the `< 3` guard, cores stayed empty, and
the code fell through to os.cpu_count() -- the LOGICAL count. Result: 6
physical cores reported as 12 (SMT over-subscription), the opposite of the
fix.

Correct per review:
  - ask lscpu for exactly 'core,socket'
  - take fields[-2], fields[-1] (correct whether or not CPU is prepended)
  - keep the warning scaffolding + the _resolve_physical_cores clamp
    (those are the actual #325 fix; only the indexing was wrong)

Test now exercises BOTH the 2-column (-p=core,socket) and 3-column
(bare -p, CPU prefix) layouts, asserting 12 physical cores each. The
2-column case is the one that regressed: old parser returns 24, new
returns 12.
This commit is contained in:
woolcoxm
2026-07-17 15:23:51 -04:00
parent bd3efb1c97
commit 171aa69fcb
2 changed files with 41 additions and 19 deletions
+16 -9
View File
@@ -212,24 +212,31 @@ def physical_cpu_count():
except (OSError, ValueError, AttributeError) as error:
_physical_cores_warn(f"Windows core probe failed: {error}")
try:
# lscpu -p prepende SEMPRE la colonna CPU, quindi `-p=core,socket` emette
# in realta' "CPU,Core,Socket" (3 colonne). Dobbiamo leggere esplicitamente
# CPU/Core/Socket e deduplicare su (core, socket): contare le righe non
# deduplicate restituirebbe i thread logici (SMT) - l'errore originale.
# I campi vuoti ("-") marcano core/socket offline e non sono interi.
result = subprocess.run(["lscpu", "-p=CPU,Core,Socket"], text=True,
# Ask lscpu for exactly core,socket and dedupe on (core, socket).
# Counting un-deduplicated rows would return logical threads (SMT),
# which was the original over-subscription bug. Empty fields ("-")
# mark an offline core/socket and fail int() -> skipped.
#
# Column layout robustness: `lscpu -p=<list>` emits *exactly* the
# requested columns (no CPU prefix), while bare `lscpu -p` prepends
# CPU. We requested two columns, but take the LAST TWO fields so the
# parser stays correct whether or not a CPU column is present
# (JustVugg review: the previous fields[1]/fields[2] indexing assumed
# a 3-column layout and regressed 2-column output to the logical
# count -- the opposite of the fix).
result = subprocess.run(["lscpu", "-p=core,socket"], text=True,
capture_output=True, check=True, timeout=5)
cores = set()
for line in result.stdout.splitlines():
if not line or line.startswith("#"):
continue
fields = line.split(",")
if len(fields) < 3:
if len(fields) < 2:
continue
try:
core, socket = int(fields[1]), int(fields[2])
core, socket = int(fields[-2]), int(fields[-1])
except ValueError:
continue # "-" per un core/socket offline
continue # "-" for an offline core/socket
cores.add((core, socket))
if cores:
return len(cores)