TGTGInsighttelegram intelligenceLIVE / telegram public index
Back to channels
Welcome to the Black Parade avatar

TGINSIGHT CHAT

Welcome to the Black Parade

@TheB1ackParade

Music

Death has many faces, I look forward to seeing this one.

Subscribers787Current channel subscribers
Tracked posts907Indexed post count
Recent reach1,209Sum of recent post views
Recent posts

Recent posts

Page 71 of 76 · 907 posts

Posted May 20

... uretprobe 对 goroutine 造成 panic, 我无语. 搞了半天, 和 ptrace 静态追踪一样不能方便地 trace 函数出口, 对 funcgraph 的绘制带来麻烦... 用 gobyexample 的例子就能复现: https://gobyexample.com/goroutines uretprobe 的实现很聪明, 修改 *($rbp+8) 的值, 这样 ret 指令就跳到用户注入的指令上而不是上层栈. 这一切也是通过函数入口的 0xcc 来搞事. 其实 ptrace…

90 views

Posted May 19

#今日我又从波波那里学到了什么 1. 爆栈就是段错误 (对不起, 我以前以为爆栈是个 errno..) 2. 没办法扩张栈空间, mmap(2) 第一参数的 addr 是给内核的 hint, 它才不会让你挨着栈空间申请内存 3. 可以捉 segv 信号, 然后啥都不处理, 进程就卡死在段错误的信号处理了 4. rlimit 的 stacksize 定义了 clone(2) 的时候传入的 stack 指针的 size, 我的 linux 上这个的默认值是 8M 5. 所以我自己调用 clone(2) 的时候应该初始化多大的栈空间, 这个问题就好办了, 听 rlimit 的话 6. 内核划分的栈空间对 go 来说都是浮云, 它直接从虚拟内存地址 0xc000000000 开始用来做栈空间, 而不是用内核指定的栈空间, 所以 go 有无限大的栈, 直到 OOM 一些其他的 tips: 1. 捕捉 segv 信号要用 sigaltstack(2) 让信号处理函数跑在堆上 2. pause(2) 挺好用的...

101 views

Posted May 18

uretprobe 的实现果然比 ptrace 这种在用户态玩弄内存和寄存器的 二流货色 高到不知道哪里去了, 我料到了它会修改 *$ra (即上层栈的 $rip) 来重定向 ret 后的执行流,我没想到这个修改过的新指令地址,连 root gdb 都不能访问,看起来是内核直接 mmap 了 4096 字节用来放 uprobe 指令,而且不设置 PROT_READ 来禁止用户态访问和修改。太硬了。

98 views

Posted May 18

double fork 变 daemon 这个我懂, blocked pipe io 是啥?

92 views

Posted May 17

我有个不成熟的暴论, libbpf 走的 CO-RE 的路线是错误的方向, 至少对 uprobe / userspace tracing 来说. 通用 userspace dynamic tracing 有以下几个条件: 1. 用户指定 binary 2. 用户指定 offset 3. 用户指定 hook trigger 时的内存操作 而第三点就是 libbpf 的阿基里斯脚踝, compile once 出来的 bpf 机器码难以根据用户需求调整; 有一些办法可以动态, 比如 BPF_PROG_ARRAY 类型的 bpf map 可以动态注册函数动态调用, 但是注册的函数也只能现场根据用户 trace 需求编译成 bpf 程序, 难以做到 CO-RE. 这一点上 bcc 和 gobpf 都是更动态的做法, 现场编译 bcc c code, 其实有更大的灵活性. 题外话, 我以后都打算使用 gobpf 了, 因为 python 解析 dwarf 性能太菜了, 我考察了好几个方案都很失望, cython 或者 ctypes 调用 libdwarf.so 的方案都要现场编译, 那还不如直接 go 呢.

105 views

Posted May 17

我草 dwarves 这个包太棒了, 计算结构体字段偏移终于不阴间了. apt install -y dwarves 然而函数入参位置的计算还是十分阴间...

98 views

Posted May 17

用 gdb 写了个 ufuncgraph 的原型, 加上时间戳之后感觉还行, 调用栈和阻塞点都一目了然. profile 就算了, 入参过滤器倒是可以做. goroutine 没有调用关系也很烦, 看不出 "谁创建了这个 goroutine" 这种信息, 只能通过时间上下文猜一下. 断点规模, 由于通过在所有的 ret 指令处注入 0xcc 来模拟 uretprobe, 所以会造成函数数量*3 这种大致规模的...断点- -

90 views

Posted May 16

... uretprobe 对 goroutine 造成 panic, 我无语. 搞了半天, 和 ptrace 静态追踪一样不能方便地 trace 函数出口, 对 funcgraph 的绘制带来麻烦... 用 gobyexample 的例子就能复现: https://gobyexample.com/goroutines uretprobe 的实现很聪明, 修改 *($rbp+8) 的值, 这样 ret 指令就跳到用户注入的指令上而不是上层栈. 这一切也是通过函数入口的 0xcc 来搞事. 其实 ptrace 也可以这么做...

105 views

Posted May 16

用 python 写了一个"优雅热更新"的 demo, 基本想法是这样的: 1. 发送信号 1 来通知更新, 进程收到后进行 fork(2) + exec(2), 其中 exec(2) 就会运行新的二进制 2. tcp listener fd 通过关闭 close on exec 的 flag 来保证 exec 后的新进程能继承, 从而平稳交接 listener fd 3. fork 出的新进程关闭 listener fd, 但是对已经建立的 client connections 继续服务, 这样做到 zero downtime 当然还有很多细节没有实现, 比如 wait(2) 子进程来避免僵尸, 还有很多状态可以横跨 exec(2) 比如 signal mask, 不过都是工程细节. 经典 zero downtime 做法是通过 unix socket 交接 fd, 本质逻辑是一样, 但是在容器时代造成的问题是, 容器进程往往是 pid ns 的一号进程, 一号进程退出会造成 os 销毁整个 pid ns, 所以要保持相同的 pid 来更新, 才想出这种方案. 然而依然没什么卵用, 无状态服务就是要随便漂节点才好做 HA, 除非真的是非常关键的服务.

103 views

Posted May 12

去年九月 meta 分享了他们用 XDP 来做服务优雅发布: https://lpc.events/event/11/contributions/950/, 我兴致勃勃想去了解 BPF_PROG_TYPE_SK_REUSEPORT 是如何解构时代难题, 看完后大失所望, 对 TCP 服务几乎没什么卵用, 和转移 listening sock + graceful term 的方案相比几乎没有什么好处却平白无故增加了复杂度, 而对真正的痛点: 新旧实例并行运行的资源占用问题, 却视而不见. 我倒是有额外几个想法: 1. 优雅热更新, 真正的热更新, pid 不变的那种, 对于古典容器是有意义的, 因为业务进程是 pid ns 的一号进程, 死了就被内核销毁全部 pid ns, 所以要原地升级. 2. server 端的 lb per call, 但 "call" 是一个业务概念, TCP 层并不能在没有额外知识的帮助下分辨什么是一个 call. http2 有 stream 的概念, 得以实现 grpc 的 lb per stream(call). 2.1. 假设有办法让 TCP 知道什么是一个 call, 那么也许可以用 bpf_msg_redirect_hash + sockmap 来实现跨进程的流量分发: 长链接 sock0 收到一个请求, 查看 sockmap, 重定向给其他 socket (可能是其他进程). 2.2. 但是和 client 端实现 lb per call 相比还是不够好, client 的实现更简单, 服务可以跨节点(sockmap 只能单节点), 所以感觉还是没什么用...

121 views

Posted May 11

perf_buffer 的 lost samples 好像没什么好办法避免,唯一能做的是通过 perf_buffer_lost_fn 参数注入一个回调,然而也只能知道丢失了多少事件。全放到 bpf map 里再读也不是不行,但是 lost samples 的本质是事件消费速度跟不上事件生产速度,如果不丢事件,那必然造成事件在内存积压,也不行。

110 views
12•••5•••10•••15•••20•••25•••30•••35•••40•••45•••50•••55•••60•••65•••6970717273•••7576