plugins/languages/c/skills/posix/SKILL.md
C POSIX systems programming conventions: file descriptor I/O with EINTR + short-read loops, directory traversal, fork/exec/waitpid, sigaction-based signal handling, BSD/POSIX sockets, and high-throughput I/O multiplexing (epoll on Linux, kqueue on macOS/BSD, poll as portable fallback). Use when writing Linux/macOS system tools, network daemons, or wrapping syscalls. Triggers on "POSIX", "fork exec", "waitpid", "sigaction", "epoll", "kqueue", "socket", "EINTR", "SO_REUSEADDR", "non-blocking IO".
npx skillsauth add lazygophers/ccplugin c-posixInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
-1 + errno 为唯一可靠错误信号。read / write 处理 EINTR 与短读短写(封装 read_all / write_all)。close 也要检查返回值(特别是写文件后)。fork 子进程退出用 _exit,不要走 atexit / stdio flush。waitpid 回收所有子进程,避免僵尸;或显式 SA_NOCLDWAIT。sigaction + sigemptyset;不用 signal()(语义跨平台不一致)。SO_REUSEADDR;现代应用同时考虑 SO_REUSEPORT。epoll(Linux) / kqueue(macOS/BSD),跨平台兜底用 poll。ssize_t read_all(int fd, void *buf, size_t n) {
size_t tot = 0;
while (tot < n) {
ssize_t r = read(fd, (char *)buf + tot, n - tot);
if (r < 0) { if (errno == EINTR) continue; return -1; }
if (r == 0) break; // EOF
tot += (size_t)r;
}
return (ssize_t)tot;
}
ssize_t write_all(int fd, const void *buf, size_t n) {
size_t tot = 0;
while (tot < n) {
ssize_t w = write(fd, (const char *)buf + tot, n - tot);
if (w < 0) { if (errno == EINTR) continue; return -1; }
tot += (size_t)w;
}
return (ssize_t)tot;
}
设置 O_CLOEXEC(open(... O_CLOEXEC)、accept4、pipe2)防止 fd 在 exec 后泄漏。
pid_t pid = fork();
if (pid < 0) { perror("fork"); return -1; }
if (pid == 0) {
execvp(argv[0], argv);
perror("execvp");
_exit(127);
}
int status;
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR) { perror("waitpid"); break; }
if (WIFEXITED(status)) /* WEXITSTATUS(status) */;
if (WIFSIGNALED(status)) /* WTERMSIG(status) */;
static volatile sig_atomic_t stop = 0;
static void on_term(int sig) { (void)sig; stop = 1; }
struct sigaction sa = { .sa_handler = on_term, .sa_flags = SA_RESTART };
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
避免 SA_RESTART 与需要超时退出的循环混用——按需选择不带 SA_RESTART 并显式处理 EINTR。
int srv = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
int one = 1;
setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
#ifdef SO_REUSEPORT
setsockopt(srv, SOL_SOCKET, SO_REUSEPORT, &one, sizeof one);
#endif
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_port = htons(8080),
.sin_addr.s_addr = htonl(INADDR_ANY),
};
bind(srv, (struct sockaddr *)&addr, sizeof addr);
listen(srv, SOMAXCONN);
非阻塞:fcntl(fd, F_SETFL, O_NONBLOCK),或 accept4(srv, ..., SOCK_NONBLOCK|SOCK_CLOEXEC)。
int ep = epoll_create1(EPOLL_CLOEXEC);
struct epoll_event ev = { .events = EPOLLIN | EPOLLET, .data.fd = srv };
epoll_ctl(ep, EPOLL_CTL_ADD, srv, &ev);
struct epoll_event evs[64];
int n = epoll_wait(ep, evs, 64, -1);
for (int i = 0; i < n; i++) { /* ... */ }
int kq = kqueue();
struct kevent ch;
EV_SET(&ch, srv, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &ch, 1, NULL, 0, NULL);
struct kevent evs[64];
int n = kevent(kq, NULL, 0, evs, 64, NULL);
poll / ppoll中等并发(<1000 fd)跨平台使用 poll;需要原子修改信号掩码用 ppoll / pselect。
mkdir 处理 EEXIST。readdir 不需要 readdir_r(已废弃,POSIX.1-2008 起 readdir 在不同 DIR 上线程安全)。pread / pwrite 避免显式 lseek。mmap 适合大文件随机访问;记得 madvise(MADV_RANDOM/SEQUENTIAL)。| 机制 | 适用 | |------|------| | pipe / pipe2 | 父子 / 兄弟 | | socketpair | 双向,跨 exec | | POSIX shm + sem | 大数据共享 | | Unix domain socket + SCM_RIGHTS | 跨进程传 fd |
read/write 处理 EINTR + 短读写O_CLOEXEC / SOCK_CLOEXEC 设置_exit,父进程 waitpid 回收sigactionSO_REUSEADDR(可选 SO_REUSEPORT)lsof 自检)tools
--- name: trellisx-workspace description: 维护 `.trellis/task.md` 任务看板 —— trellis 缺的跨任务总览。**一个表格, 一行一个任务**, 列为 id/名称/描述/状态/阶段/进度/worktree (状态/阶段中文显示)。在 task create/start/阶段切换/archive 后**及时更新**对应行; 并**自动清理超 7 天的已完成行**防膨胀。保持看板与 task.json 实时一致。 when_to_use: 维护 / 创建 / 更新 `.trellis/task.md` 任务看板时; task 生命周期任一节点 (create/start/阶段推进/archive) 之后同步看板时; 用户问"当前有哪些任务 / 任务进度 / 任务看板"时。被 trellisx-flow 与 trellisx-apply 注入的流程引用。 user-invocable: true argument-hint: [show|update|sync|cleanup ...] [task id] arguments:
testing
强制以 Trellis task 闭环处理用户指定的请求 (自判新建/并入 → plan→exec→check→finish 全程不跳步)。**仅用户显式主动调用** (/trellisx-flow 或明确要求"强制走 task 处理这个"); **禁止自动 / 被动 / 推断式调用** —— 不要因为某个请求"看起来该建 task"就自动触发本 skill, 那是 apply 注入的 no_task 倾向的职责。
testing
把 强推task + subtask拆分 + worktree隔离 + 闭环收尾 四维度增量注入当前项目 .trellis/ (workflow.md 的 no_task/planning/in_progress 块 + spec 背书文档 + trellis 生命周期 hook worktree 自动化)。强推 task 与闭环为纯 prompt 软约束 (非平台 hook 硬拦截)。**纯增量追加, 绝不替换 trellis 原生文本** (no_task 分类+征同意/check/finish/前缀全保留)。幂等 (marker 包裹)。
development
Claude Code 会话历史整理 — 扫 ~/.claude/projects/**/*.jsonl 全部 session transcripts, 提取学习增量 (用户校正/决策/踩坑/L0 规则) → 全局记忆库 ~/.cortex/.wiki/memory/. 默认 --apply 落盘 (--dry-run opt-in 仅出 JSON plan 预览). 与 cortex-extract (L4-inbox 内部) 互补.