Memo

共 15 条灌水 · 4

修复 Zig TSan 找不到 linux/scc.h

新版 Linux headers 上启用 Zig ThreadSanitizer,构建在项目代码编译前就失败:

error: sub-compilation of libtsan failed
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp:160:10:
error: 'linux/scc.h' file not found
#include <linux/scc.h>
         ^~~~~~~~~~~~~

不是项目代码的并发问题。Zig 的 -fsanitize-thread 首次构建时会从安装目录里的源码编译一份 ThreadSanitizer runtime,以 Zig 0.16.0 为例在 <zig-lib-dir>/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp。这份 vendored libtsan 里有三行死代码:

#include <linux/scc.h>

unsigned struct_scc_modem_sz = sizeof(struct scc_modem);
unsigned struct_scc_stat_sz = sizeof(struct scc_stat);

Linux 内核删掉了废弃的 SCC amateur-radio 接口,linux/scc.h 也从 UAPI headers 里消失,滚动发行版先撞上。LLVM compiler-rt 已通过 #194116 移除这三处引用,但 Zig 用的是自己的快照,要等发布包同步才算修好。

补丁

仓库里建 .mise/tasks/fix/zig-tsan

#!/usr/bin/env bash
#MISE description="Patch Zig libtsan for Linux headers without linux/scc.h"
set -euo pipefail

if [ "$(uname -s)" != Linux ]; then
    echo "Zig libtsan scc.h patch is only needed on Linux"
    exit 0
fi

zig_exe=$(readlink -f "$(command -v zig)")
zig_lib_dir=${ZIG_LIB_DIR:-"$(dirname "$zig_exe")/lib"}
source_file="$zig_lib_dir/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp"

if [ ! -f "$source_file" ]; then
    echo "error: Zig libtsan source not found: $source_file" >&2
    exit 1
fi

include='#include <linux/scc.h>'
modem='  unsigned struct_scc_modem_sz = sizeof(struct scc_modem);'
stats='  unsigned struct_scc_stat_sz = sizeof(struct scc_stat);'

remaining=0
for line in "$include" "$modem" "$stats"; do
    count=$(grep -Fxc "$line" "$source_file" || true)
    if [ "$count" -gt 1 ]; then
        echo "error: unexpected duplicate in Zig libtsan: $line" >&2
        exit 1
    fi
    remaining=$((remaining + count))
done

if [ "$remaining" -eq 0 ]; then
    echo "Zig $(zig version) libtsan is already compatible with current Linux headers"
    exit 0
fi

if [ "$remaining" -ne 3 ]; then
    echo "error: Zig libtsan is only partially compatible; refusing to modify it" >&2
    exit 1
fi
if [ ! -w "$source_file" ]; then
    echo "error: Zig libtsan source is not writable: $source_file" >&2
    exit 1
fi

sed -i \
    -e "\\|^$include\$|d" \
    -e "\\|^$modem\$|d" \
    -e "\\|^$stats\$|d" \
    "$source_file"

for line in "$include" "$modem" "$stats"; do
    if grep -Fxq "$line" "$source_file"; then
        echo "error: failed to remove obsolete Zig libtsan reference: $line" >&2
        exit 1
    fi
done

echo "Patched Zig $(zig version) libtsan: $source_file"
chmod +x .mise/tasks/fix/zig-tsan
mise run fix:zig-tsan

任务靠 command -v zigreadlink 定位 mise 当前选中的 Zig,不硬编码版本目录。三行目标代码必须各出现一次才动手:都在就补,都不在就输出 already compatible 直接退出,部分存在或重复则拒绝改。所以可以重复执行,Zig 同步上游修复后也不用删。

验证

清掉独立的 TSan 构建缓存,让 runtime 用修补后的源码重新编译:

rm -rf .zig-cache/tsan
mise run test:tsan

没有封装测试任务就重跑原来的 zig build,保留 -fsanitize-thread 或对应 build option。重新安装或切换 Zig 版本后 mise 会建新的工具链目录,需要再跑一次补丁。

参考

ArchLinux 编译 python-kornia-rs

安装 python-kornia-rs 失败,构建的时候 g 了。

直接一把梭搞定。

user@host [23:50:58] [~/.cache/yay/python-kornia-rs] [master *]
-> % makepkg -s
==> Making package: python-kornia-rs 0.1.9-5 (Thu 24 Jul 2025 11:51:05 PM CST)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Found kornia-rs-0.1.9.tar.gz
==> Validating source files with sha256sums...
    kornia-rs-0.1.9.tar.gz ... Passed
==> Extracting sources...
  -> Extracting kornia-rs-0.1.9.tar.gz with bsdtar
==> Removing existing $pkgdir/ directory...
==> Starting build()...
* Getting build dependencies for wheel...
* Building wheel...
Running `maturin pep517 build-wheel -i /usr/bin/python --compatibility off`
🔗 Found pyo3 bindings
💥 maturin failed
  Caused by: Python interpreter should be a kind of interpreter (e.g. 'python3.8' or 'pypy3.9') when cross-compiling, got path to interpreter: /usr/bin/python
Error: command ['maturin', 'pep517', 'build-wheel', '-i', '/usr/bin/python', '--compatibility', 'off'] returned non-zero exit status 1

ERROR Backend subprocess exited when trying to invoke build_wheel
==> ERROR: A failure occurred in build().
    Aborting...
export PYO3_CROSS_PYTHON_VERSION=3.13
export PYO3_CROSS_LIB_DIR=/usr/lib
export CARGO_BUILD_TARGET=x86_64-unknown-linux-gnu
makepkg -sf

-> % ls -lah
total 2.8M
drwxr-xr-x 1 user user  310 Jul 24 23:53 .
drwxr-xr-x 1 user user  358 Jul 24 23:17 ..
drwxr-xr-x 1 user user  140 Jul 24 23:49 .git
-rw-r--r-- 1 user user 235K Jul 24 23:17 kornia-rs-0.1.9.tar.gz
-rw-r--r-- 1 user user   96 Jul 24 23:17 .nvchecker.toml
drwxr-xr-x 1 user user   76 Jul 24 23:53 pkg
-rw-r--r-- 1 user user 1.1K Jul 24 23:52 PKGBUILD
-rw-r--r-- 1 user user 2.3M Jul 24 23:53 python-kornia-rs-0.1.9-5-x86_64.pkg.tar.zst
-rw-r--r-- 1 user user 252K Jul 24 23:53 python-kornia-rs-debug-0.1.9-5-x86_64.pkg.tar.zst
drwxr-xr-x 1 user user   74 Jul 24 23:52 src
-rw-r--r-- 1 user user  793 Jul 24 23:17 .SRCINFO

-> % sudo pacman -U python-kornia-rs-0.1.9-5-x86_64.pkg.tar.zst

关闭 macOS 监听的端口 5000

我很喜欢 sigoden/dufs 这个项目,启动一个 HTTP server 还是共享文件,都非常方便。

但是 macOS 下会有一个烦人的家伙占用 5000 端口。

-> % dufs
Error: Failed to bind `0.0.0.0:5000`

Caused by:
    Address already in use (os error 48)

抓一下。

-> % sudo lsof -i -P | grep ":5000"
ControlCe   629        fanyang   12u  IPv4 0xdc924348e03ccb2f      0t0    TCP *:5000 (LISTEN)
ControlCe   629        fanyang   13u  IPv6 0xcb88b5ec8a71ad1a      0t0    TCP *:5000 (LISTEN)

好家伙,原来是 Control Center。这就把你干了。

Why always something is running at port 5000 on my mac

For fixing this you need to turn off System Settings > General > AirDrop & Handoff > AirPlay Receiver.

image.png

嗯,确实没了,很好。

一键清理空的 Github Repo

在 GitHub 上创建了一堆 repository 但是又没空写,怎么把这些空的 repository 都删了呢?

写了一个小脚本 find-empty-github-repo 把他们都删了。

使用方法

  1. 点击这里创建一个 token,并且具有 repo 权限。

  2. 创建一个 .env 把 token 填进去,然后运行脚本。

详细的操作参考 README.md

常用 Go modules

鄙人常用的一些 go mod,备查

存数据

  • github.com/cockroachdb/pebble
  • github.com/mattn/go-sqlite3
  • github.com/spf13/afero
  • github.com/syndtr/goleveldb
  • gorm.io/gorm
  • gorm.io/driver/sqlite

错误处理

  • github.com/cockroachdb/errors

哈希

  • github.com/cespare/xxhash

测试

  • github.com/negrel/assert
  • github.com/stretchr/testify

命令行

  • github.com/urfave/cli/v3
  • github.com/schollz/progressbar/v3
  • github.com/joho/godotenv

日志

  • github.com/rs/zerolog
  • github.com/fanyang89/pzlog
  • github.com/outrigdev/outrig

字符串

  • github.com/gobwas/glob

缓存

  • github.com/maypok86/otter

破解 Delete All Google Photos 插件

自从有了 NAS 之后,就想把所有云的会员都取消了。但上云容易下云难

上传到 Google Photos 的时候爽的不行,结果现在会员到期了,空间直接给我爆了,还不让我发邮件。

一番搜索,发现了一个插件,可以自动化删除所有的照片:Delete All Google Photos

扩展 ID:bebhhjmapjadpdkkhbkpnpbjhkhndofl

试用版每天只能删 500 张,根本不好使啊。我直接反手一个 js 的读。

找到下面的代码段:

const R = 1e3,
  M = 1000000;
function E(i) {
  return new Promise((e) => setTimeout(e, i));
}

M 改成很大的值。

if (
  !!P &&
  (console.log("removing undo delete button and continuing", new Date()),
  P.remove(),
  (r += b),
  localStorage.setItem("num_deleted", 0),
  localStorage.setItem("last_deleted_at", new Date().getTime()),
  !(o != null && o.paid) && r >= M)
) {
  t(0, (p = !0));
  return;
}

每次 r += b 然后设置 num_deleted。改成每次 num_deleted 都设置为 0

然后开发人员模式加载扩展,直接一把梭删完,爽!

配置 npm 与 node-gyp 镜像

npm set registry https://registry.npmmirror.com
npm set disturl https://npmmirror.com/mirrors/node

按需补充二进制下载镜像:

npm set sass_binary_site https://registry.npmmirror.com/mirrors/node-sass
npm set electron_mirror https://registry.npmmirror.com/mirrors/electron
npm set puppeteer_download_host https://registry.npmmirror.com/mirrors
npm set chromedriver_cdnurl https://registry.npmmirror.com/mirrors/chromedriver

修复 xfs.h 的 void 指针算术错误

Clang 编译 XFS 头文件时,void * 不能直接参与指针算术。将:

void *next = ((void *)gpr + gpr->gpr_reclen);
return next;

改为:

void *next = ((char *)gpr + gpr->gpr_reclen);
return (struct xfs_getparents_rec *)next;

使用 Git LFS 管理大文件

初始化 Git LFS:

git lfs install

追踪 ISO 并提交:

git lfs track "*.iso"
git add .gitattributes
git add file.iso
git commit -m "Add disk image"
git push