amanusk / amanusk/s-tui

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

Open Beginner friendly
#304 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
5.1k
Forks
181
Avg merge
30m
Merged PRs (30d)
2

Description

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.

Contributor guide

Open the contributing guide

Research direction

Start in s_tui/sources/util_source.py, especially update() and _get_online_cpu_ids(), and reproduce the issue with chcpu and taskset on Linux if available. Verify that online CPU IDs remain distinct from the process affinity mask and that only offline CPUs display N/A; add or update focused tests if the existing source tests cover this path.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, python
Domain
cli, operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.