ilmanzo / ilmanzo/BinaryCoverage
cancel, lp, lpoptions, nfsrahead report 0% coverage despite being executed
@ilmanzo is already working on this.
Since Aug 31, 2026.
- Dominant language
- C
- Stars
- 9
- Forks
- 6
- Avg merge
- 1h 32m
- Merged PRs (30d)
- 11
Description
> **Edited 2026-08-31.** The original body proposed two debuginfo-packaging causes. Both were **wrong** and have been retracted — see [this comment](https://github.com/ilmanzo/BinaryCoverage/issues/158#issuecomment-5475990530) for the retraction, a reproducer script, and a verified patch. This body now describes the actual findings.
## Observation
openQA job https://openqa.opensuse.org/tests/6194777 reports **0% function coverage** for binaries that definitely execute during the test:
- `cancel`, `lp`, `lpoptions` — console/cups (`coverage_targets` key `cups-client`)
- `nfsrahead` — console/rpcbind, console/postgresql_server (key `nfs-client`)
Schedule: `cups_rpcbind_coverage.yaml`. The `coverage_targets` mapping is correct — binaries are keyed under their real owning packages, so `coverage_setup.pm` does request `cups-client-debuginfo` and `nfs-client-debuginfo`, and both exist and are complete. **Debuginfo packaging is not the problem.**
Two independent root causes, both reproduced on an openSUSE Tumbleweed VM.
## A — `lp` / `cancel` / `lpoptions`: the only instrumented function is the error path
Not a tracing failure. CUPS 2.4.19 `systemv/lp.c` defines four functions: `main` (on funkoverage's `funcBlacklist`), `restart_job` and `set_job_attrs` (static, inlined away, absent from `.symtab`), and `usage` (`_CUPS_NORETURN`, reached only from `--help` or an argument error — 17 call sites, all error paths).
So the entire instrumented set is `usage`, and a successful run can never reach it:
```
$ funkoverage enumerate --no-libs /usr/bin/lp
/usr/bin/lp usage
Total: 1 functions across 1 image(s)
normal run (lp -d nonexistent /etc/hostname) : 0 functions called -> 0%
help run (lp --help) : 1 function called -> 100%
```
The traceable-function count predicts the reported set exactly — including the binaries that were **not** reported:
| binary | traceable functions | reported 0%? |
|---|---|---|
| `lp`, `cancel` | 1 (`usage`) | ✅ |
| `lpoptions` | 2 | ✅ |
| `lpadmin` | 3 | ❌ |
| `lpstat` | 10 | ❌ |
The 0% is arithmetically correct but indistinguishable from "never executed".
## B — `nfsrahead`: the shim aborts under udev, so the binary never runs at all
`nfsrahead` is a udev callout (`99-nfs.rules`: `SUBSYSTEM=="bdi", ACTION=="add", PROGRAM="/usr/libexec/nfsrahead %k"`), not a shell command.
- Direct invocation from a root shell → 10 functions traced, fine.
- Invocation by udev → **0**, every `_called.log` 0 bytes.
```
11:0: '/usr/libexec/nfsrahead 11:0'(err) 'funkoverage-shim: helper: tracer start: \
tracer: attach fork tracepoint: ope...'
11:0: Process '/usr/libexec/nfsrahead 11:0' failed with exit code 1.
```
`Tracer.Start()` aborts at `link.Tracepoint("sched","sched_process_fork")` — the only attach needing `perf_event_open(2)` rather than `bpf(2)`. systemd-udevd's seccomp allow-list has `bpf` but **not** `perf_event_open` (capabilities are fine: its bounding set includes `cap_bpf`, `cap_perfmon`, `cap_sys_admin`). Allowing just that syscall makes coverage appear immediately.
**This is worse than lost coverage:** the error propagates to `os.Exit(1)` *before* `syscall.Exec(realBin)`, so while shimmed, udev's callout is a stub that always fails — `nfsrahead` never runs and NFS readahead tuning silently breaks. Any shimmed binary invoked from a seccomp-sandboxed unit hits this.
## Proposed fix
Implemented and verified (see the [comment](https://github.com/ilmanzo/BinaryCoverage/issues/158#issuecomment-5475990530) for the diff and reproducer):
1. **Remove `main` from `funcBlacklist`** — it is the one entry point that is real user code, and the liveness signal that separates "ran" from "never ran".
2. **Make the fork tracepoint non-fatal** — it only extends tracing to children; degrade instead of aborting.
3. **Fail open in `runWithTracing`** — if the tracer can't attach, warn and exec the real binary anyway. Never replace the user's program with a failing stub.
| case | before | after |
|---|---|---|
| `lp -d nonexistent file` | 0/1 → 0% | 1/2 → 50% |
| `nfsrahead` via udev | 0/16 → 0%, binary never ran | 10/16 → 62.5%, binary runs |
Environment: openSUSE Tumbleweed, `cups-2.4.19-2.3`, `nfs-client-2.9.2-54.1`, BinaryCoverage @ `5907733`.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.