麻了,debugger 的观测者效应真是防不胜防。

比如 sudo strace -fT [cmd] , 会改变 [cmd] 的 stdout 的 F_GETFL,想不到吧!因为大家都以为 [cmd] 会直接继承 stdout,理应不改变任何设定;而大家的以为也是正确的,strace [cmd] 确实直接继承,不玩花的。

这里的问题非常隐蔽,问题出在 sudo 而不是 strace。 sudo [cmd] 会形成一对父子进程,sudo 会新创建伪终端传递给 [cmd] 的 stdio,这一步的伪终端改变了 stdout F_GETFL。

那么 F_GETFL 又有什么影响呢?在 go1.22 里新增了一个 API net#TCPConn.WriteTo , 这个 API 底层兼容各种 syscall,会尝试使用最好的 API。里面有一步骤的逻辑是判断 WriteTo 的 io.Writer 是否 appendModeL,如果 appendMode 就走 copy_file_range(2),否则走 splice(2)。新创建 pty 恰好改变了 stdout appendMode,从而改变了 WriteTo() 底层调用的 syscall。

这一层封装理应不影响用户,除非遇到内核 bug。 bpf_msg_redirect 和 splice 一起使用的时候会遇到内核 bug 导致 splice 读不到数据,而 golang 程序是否使用 splice(2) 又受观察者影响,真是太棒了!

说不定量子论的底层逻辑正是如此,观测方式不同 (stdout 的类型不同)就会影响观测结果,很合理 太民科了,划掉
 
 
Back to Top