Call begin at: 2021-02-06 06:13:14 finish at: 2021-02-06 06:13:17 call take: 3001 ms
Call begin at: 2021-02-06 06:13:17 finish at: 2021-02-06 06:13:20 call take: 3002 ms
Call begin at: 2021-02-06 06:13:20 finish at: 2021-02-06 06:13:23 call take: 3001 ms
使用 bpftool 查看正在运行的 BPF 程序,没毛病。
[root@localhost ~]# bpftool prog show | grep kprobe 228: kprobe name uretprobe__5997 tag 16fb156ad25a6b14 gpl 229: kprobe name uprobe__5997184 tag 55496f0b3bc88275 gpl
print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n") if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 { print("signal arrived during cgo execution\n") gp = _g_.m.lockedg.ptr() } if sig == _SIGILL || sig == _SIGFPE { // It would be nice to know how long the instruction is. // Unfortunately, that's complicated to do in general (mostly for x86 // and s930x, but other archs have non-standard instruction lengths also). // Opt to print 16 bytes, which covers most instructions. const maxN = 16 n := uintptr(maxN) // We have to be careful, though. If we're near the end of // a page and the following page isn't mapped, we could // segfault. So make sure we don't straddle a page (even though // that could lead to printing an incomplete instruction). // We're assuming here we can read at least the page containing the PC. // I suppose it is possible that the page is mapped executable but not readable? pc := c.sigpc() if n > physPageSize-pc%physPageSize { n = physPageSize - pc%physPageSize } print("instruction bytes:") // <-- 在这里打印的非法指令 b := (*[maxN]byte)(unsafe.Pointer(pc)) for i := uintptr(0); i < n; i++ { print(" ", hex(b[i])) } println() } print("\n")
level, _, docrash := gotraceback()
// 接下来程序进入 level>0 的分支 if level > 0 { // 打印 goroutine 现场 goroutineheader(gp) tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), gp) if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { // tracebackothers on original m skipped this one; trace it now. goroutineheader(_g_.m.curg) traceback(^uintptr(0), ^uintptr(0), 0, _g_.m.curg) } elseif crashing == 0 { tracebackothers(gp) print("\n") } dumpregs(c) }
// 一旦到了这里 那进程就必定会退出了 if docrash { crashing++ if crashing < mcount()-int32(extraMCount) { // There are other m's that need to dump their stacks. // Relay SIGQUIT to the next m by sending it to the current process. // All m's that have already received SIGQUIT have signal masks blocking // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. // When the last m receives the SIGQUIT, it will fall through to the call to // crash below. Just in case the relaying gets botched, each m involved in // the relay sleeps for 5 seconds and then does the crash/exit itself. // In expected operation, the last m has received the SIGQUIT and run // crash/exit and the process is gone, all long before any of the // 5-second sleeps have finished. print("\n-----\n\n") raiseproc(_SIGQUIT) usleep(5 * 1000 * 1000) } crash() }