close
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 74/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- bash, macos
- Domain
- devops, observability
Research direction
Start with /Library/NullMoth/nullmoth-displaytrace.sh as generated in nullmoth-setup.sh (the issue cites the v1.12.0 and v1.13.0 heredoc locations) and compare its kext check with the wait loop in nullmoth-wsreset.sh. Check the display trace launchd plist for its startup behavior. Done means the tracker creates its directory and starts recording when the kext loads after launchd starts it; verify the boot timing path described in the issue.
Written by the indexing model from the issue text.
Description
What happens
On this machine the display tracker records nothing. /Library/NullMoth/display-trace/ does not exist, so
Send logs uploads no display-trace.txt / display-kernel.txt / display-ws.txt, and the app's
Record the flicker does nothing either — it only appends its == USER: flicker seen now marker when that
directory exists.
This is on both 1.12.0 and 1.13.0, freshly installed and rebooted.
Evidence
$ ls -la /Library/NullMoth/display-trace/
ls: /Library/NullMoth/display-trace/: No such file or directory
$ launchctl print system/com.nullmoth.displaytrace
state = not running
runs = 1
last exit code = 0
The daemon ran exactly once and exited 0 — without creating its own directory. mkdir -p is on line 4, so the
run ended before it.
Why
/Library/NullMoth/nullmoth-displaytrace.sh line 3:
kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel || exit 0
That is the only exit 0 before the mkdir, so the gate is where it stopped: at the moment launchd started it,
kextstat did not yet list com.nullmoth.NVAccel. The plist has RunAtLoad and no KeepAlive, so there is
no second attempt and no retry.
The gate is not wrong — it passes now, which I checked by hand:
$ kextstat 2>/dev/null | grep -c com.nullmoth.NVAccel
1
So it is a race, not a bad test. The neighbouring daemon shows the difference: nullmoth-wsreset.sh waits for its
dependency before using it —
for i in $(seq 1 40); do pgrep -x WindowServer >/dev/null 2>&1 && break; sleep 1; done
— and it does run (/var/run/nullmoth-wsreset.done exists and wsreset.log was written at this boot). The
tracker checks once, immediately, and gives up for the whole boot.
What it costs
Both halves of the display-evidence path are gated on that directory, in nullmoth-setup.sh:
# line 150 — Record the flicker
[ -d /Library/NullMoth/display-trace ] && echo "== USER: flicker seen now $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> /Library/NullMoth/display-trace/trace.txt
# line 261 — Send logs
[ -f "/Library/NullMoth/display-trace/$f" ] && tail -c 3145728 "/Library/NullMoth/display-trace/$f" > "$COLLECT/display-$f"
So the 1.12 release note — "Send logs uploads it, so if your screen went black, restart, then press Send logs; we
can see what happened" — yields nothing on a machine where the gate lost the race. The open item for black
screens above 60 Hz asks for exactly this data, and a user who follows the instruction will believe they sent it.
Suggested fix
Wait for the kext the way wsreset waits for WindowServer, and keep the gate as the final check:
for i in $(seq 1 60); do kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel && break; sleep 1; done
kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel || exit 0
Or add KeepAlive with a ThrottleInterval, or drop the gate entirely — the two log stream pipelines are
harmless when no NullMoth kext is loaded, and the loop already does nothing useful without the counters.
Workaround for a user who needs the trace now
sudo launchctl kickstart -k system/com.nullmoth.displaytrace
The gate passes once the kexts are up, so the directory appears and the loop starts. It does not survive the next
boot.
Environment
RTX 3080 10 GB (10DE:2206), macOS 15.8.1 (24H32), OpenCore. Driver 1.12.0 then 1.13.0; the gate line is identical
in both (nullmoth-setup.sh heredoc at v1.12.0 L915 and v1.13.0 L1024).
中文版(Chinese version)
发生了什么
本机的 display tracker 什么都没记录。/Library/NullMoth/display-trace/ 不存在,因此 Send logs 不会上传任何
display-trace.txt / display-kernel.txt / display-ws.txt;app 的 Record the flicker 同样什么也不做
—— 它只在那个目录存在时才追加 == USER: flicker seen now 标记。
1.12.0 和 1.13.0 都是如此(全新安装 + 重启)。
证据
$ ls -la /Library/NullMoth/display-trace/
ls: /Library/NullMoth/display-trace/: No such file or directory
$ launchctl print system/com.nullmoth.displaytrace
state = not running
runs = 1
last exit code = 0
daemon 只跑过一次并以 0 退出 —— 而且没有创建自己的目录。mkdir -p 在第 4 行,所以它在到达那一行之前就结束了。
原因
/Library/NullMoth/nullmoth-displaytrace.sh 第 3 行:
kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel || exit 0
这是 mkdir 之前唯一的 exit 0,所以它卡在门槛上:launchd 启动它的那一刻,kextstat 还没有列出
com.nullmoth.NVAccel。plist 是 RunAtLoad 且没有 KeepAlive ⇒ 没有第二次尝试,也没有重试。
门槛本身没错 —— 我手工验证过,现在能通过:
$ kextstat 2>/dev/null | grep -c com.nullmoth.NVAccel
1
所以这是竞态,不是测试写错。相邻的 daemon 正好是对照组:nullmoth-wsreset.sh 会先等它的依赖 ——
for i in $(seq 1 40); do pgrep -x WindowServer >/dev/null 2>&1 && break; sleep 1; done —— 它确实跑起来了
(/var/run/nullmoth-wsreset.done 存在,本次启动也写了 wsreset.log)。tracker 只检查一次,立刻放弃,整次启动
都不再有。
代价
显示证据链的两半都依赖那个目录(nullmoth-setup.sh):
# 第 150 行 —— Record the flicker
[ -d /Library/NullMoth/display-trace ] && echo "== USER: flicker seen now ..." >> /Library/NullMoth/display-trace/trace.txt
# 第 261 行 —— Send logs
[ -f "/Library/NullMoth/display-trace/$f" ] && tail -c 3145728 "/Library/NullMoth/display-trace/$f" > "$COLLECT/display-$f"
因此 1.12 的 release note ——「Send logs 会上传它,所以如果屏幕黑了,重启后按 Send logs,我们就能看到发生了什么」
—— 在门槛输掉竞态的机器上什么也拿不到。而「>60 Hz 黑屏」这个 open 项要的正是这份数据,照做的用户会以为
自己发出去了。
建议修法
像 wsreset 等 WindowServer 那样等 kext,并把门槛留作最后一道检查:
for i in $(seq 1 60); do kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel && break; sleep 1; done
kextstat 2>/dev/null | grep -q com.nullmoth.NVAccel || exit 0
或者加 KeepAlive + ThrottleInterval,或者干脆去掉门槛 —— 没有 NullMoth kext 时那两条 log stream 无害,
而没有计数器时主循环本来也做不了有用的事。
需要立刻拿到 trace 的用户的临时办法
sudo launchctl kickstart -k system/com.nullmoth.displaytrace
kext 加载后门槛就能过,目录会出现、循环会开始。但它熬不过下一次重启。
环境
RTX 3080 10GB(10DE:2206),macOS 15.8.1 (24H32),OpenCore。驱动 1.12.0 → 1.13.0;两版的门槛行完全相同
(nullmoth-setup.sh 的 heredoc:v1.12.0 L915、v1.13.0 L1024)。
- Dominant language
- Rust
- Stars
- 2.5k
- Forks
- 233
- Avg merge
- 1h 37m
- Merged PRs (30d)
- 1
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
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.
More from nullmoth/nvidia-macos-driver
-
[Bug] `nullmoth-wsreset.sh` never restarts WindowServer at the real login window: `/dev/console` is `_windowserver`, not `root` (guard + test blind spot)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
nullmoth/nvidia-macos-driver#141 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
nullmoth/nvidia-macos-driver#28 ·
Maintainers usually reply within 2 days
-
Difficulty 4/5 Over a week Newbie friendliness 12/100
nullmoth/nvidia-macos-driver#248 ·
Maintainers usually reply within 2 days
-
bug
Difficulty 5/5 Over a week Newbie friendliness 12/100
nullmoth/nvidia-macos-driver#246 · 2 comments ·
Maintainers usually reply within 2 days
-
bug
Difficulty 5/5 Over a week Newbie friendliness 12/100
nullmoth/nvidia-macos-driver#244 ·
Maintainers usually reply within 2 days
All issues in nullmoth/nvidia-macos-driver
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
pop-os/cosmic-comp#2956 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
area:release criticality:p3 documentation
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
registrystack/registry-stack#2085 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
libp2p/rust-libp2p#6694 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
EmbarkStudios/cargo-deny#910 ·