amanusk / amanusk/s-tui

Util shows N/A on online cores when taskset is combined with offlined CPUs

Abierto
#304 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
5.1k
Forks
181
Merge medio
30 min
PR fusionados (30 d)
2

Descripción

Follow-up to #303. The fix for #303 handles `taskset` (all CPUs online) and pure `chcpu -d` (no taskset) correctly, but the combination of the two still misreports online cores as N/A.

## Repro

On an 8-core machine:

```
sudo chcpu -d 4
taskset -c 3-6 s-tui
```

Cores actually online: 0, 1, 2, 3, 5, 6, 7. Only core 4 is offline.
s-tui displays: cores 3, 5, 6 with values; cores 0, 1, 2, 4, 7 as N/A.
Expected: only core 4 as N/A.

## Root cause

In `s_tui/sources/util_source.py::update()`, when `len(per_cpu) < total_cores` we fall back to `_get_online_cpu_ids()`, which calls `psutil.Process().cpu_affinity()`. Under taskset that returns the intersection of the taskset mask and the online set (here `[3, 5, 6]`), not the full online set (`[0, 1, 2, 3, 5, 6, 7]`).

`psutil.cpu_percent(percpu=True)` returns 7 values (one per online CPU) but we only know the real IDs of 3 of them, so `zip(online_ids, per_cpu)` truncates and every non-affinity core is marked N/A.

## Why psutil can't answer this

psutil has no API that returns "online CPU IDs" independent of process affinity. `cpu_affinity()` always intersects with the caller's mask; `cpu_count()` gives a number, not IDs; `cpu_percent(percpu=True)` gives values indexed 0..N-1 that don't map to real CPU IDs when there are gaps.

## Proposed fix

Read `/sys/devices/system/cpu/online` (Linux-only, but so is chcpu). Parse the cpulist format (`0-3,5,7`) into the online-ID list. Cadence stays the same as today — we only refresh `_cached_online_ids` when `len(per_cpu)` changes, so this is one file read at startup plus one on each hotplug event, not per update cycle.

Sketch:

```python
def _get_online_cpu_ids() -> list[int] | None:
try:
with open("/sys/devices/system/cpu/online") as f:
raw = f.read().strip()
except OSError:
return None
ids = []
for chunk in raw.split(","):
if "-" in chunk:
a, b = chunk.split("-")
ids.extend(range(int(a), int(b) + 1))
else:
ids.append(int(chunk))
return ids
```

## Scope note

This is a rare combination and was equally broken before 1.4.0 (offline detection didn't exist), so it's not a regression — just a limitation of the offline-detection feature added in #262.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.