Updated: I extract the core code to a pure c program, it trigger SIGSEGV as expected. And I had also post it on stackoverflow <https://stackoverflow.com/questions/77165821/golangcgo-using-ucontext-crashon-purpose-crash-with-sigsegv-or-sigtrap-while>, which support markdown and will be more visualable with code. 在2023年9月24日星期日 UTC+8 13:32:19<zk Z> 写道:
> Hi all, > > I'm currently writing a Golang + CGO program, and will use posix ucontext > in CGO. Since all my core logic will be in the bind function of ucontext, > we should catch up all the bad code. And I test it by accessing to the null > pointer, which give me totally different behaviors that all depending on > the stack location which ucontext used. Here are more details with > simplified example. > > *If I allocate the ucontext stack on the thread's stack, it will trigger > SIGSEGV. But if I allocate it on the heap, it will first trigger SIGSEGV, > and then SIGTRAP while calling `morestack_noctxt` before calling into > `runtime.sigpanic`.* How can I fix this or how can I just get SIGSEGV? > Why it need morestack? > > Here is my guess, but seems not correct: *when I used the malloc stack, > it was treat as it has stack overflow, and should more stack, but end up > find it's g0, then fatal. But it seems the goroutine's stack is much more > lower address than thread's stack?* > > All below are details, any suggestions or comments will be appreciated. > Thanks! > > Crash(with malloc stack): > > ```go > fatal: morestack on g0 > SIGTRAP: trace trap > PC=0x45f342 m=0 sigcode=128 > signal arrived during cgo execution > > goroutine 1 [syscall]: > runtime.cgocall(0x464870, 0xc000067f60) > /usr/local/go/src/runtime/cgocall.go:157 +0x5c fp=0xc000067f38 > sp=0xc000067f00 pc=0x40465c > main._Cfunc_core_logic() > _cgo_gotypes.go:39 +0x45 fp=0xc000067f60 sp=0xc000067f38 pc=0x4646e5 > main.coreLogic() > /container_share/works/badstack/main.go:46 +0x17 fp=0xc000067f70 > sp=0xc000067f60 pc=0x464737 > main.main() > /container_share/works/badstack/main.go:51 +0x17 fp=0xc000067f80 > sp=0xc000067f70 pc=0x464777 > runtime.main() > /usr/local/go/src/runtime/proc.go:250 +0x1d3 fp=0xc000067fe0 > sp=0xc000067f80 pc=0x436913 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000067fe8 > sp=0xc000067fe0 pc=0x45f4a1 > > goroutine 2 [force gc (idle)]: > runtime.gopark(0x47a860, 0x6cb4d0, 0x11, 0x14, 0x1) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000054f88 > sp=0xc000054f58 pc=0x436dbd > runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000054fb8 > sp=0xc000054f88 pc=0x436e4a > runtime.forcegchelper() > /usr/local/go/src/runtime/proc.go:305 +0xb0 fp=0xc000054fe0 > sp=0xc000054fb8 pc=0x436b90 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000054fe8 > sp=0xc000054fe0 pc=0x45f4a1 > created by runtime.init.6 > /usr/local/go/src/runtime/proc.go:293 +0x25 > > goroutine 3 [GC sweep wait]: > runtime.gopark(0x47a860, 0x6cb640, 0xc, 0x14, 0x1) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055758 > sp=0xc000055728 pc=0x436dbd > runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055788 > sp=0xc000055758 pc=0x436e4a > runtime.bgsweep(0x0?) > /usr/local/go/src/runtime/mgcsweep.go:278 +0x98 fp=0xc0000557c8 > sp=0xc000055788 pc=0x421998 > runtime.gcenable.func1() > /usr/local/go/src/runtime/mgc.go:178 +0x26 fp=0xc0000557e0 sp=0xc0000557c8 > pc=0x415f66 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000557e8 > sp=0xc0000557e0 pc=0x45f4a1 > created by runtime.gcenable > /usr/local/go/src/runtime/mgc.go:178 +0x6b > > goroutine 4 [GC scavenge wait]: > runtime.gopark(0x47a860, 0x6cb6c0, 0xd, 0x14, 0x2) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055f48 > sp=0xc000055f18 pc=0x436dbd > runtime.goparkunlock(0x47ca80?, 0x1?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055f78 > sp=0xc000055f48 pc=0x436e4a > runtime.(*scavengerState).park(0x6cb6c0) > /usr/local/go/src/runtime/mgcscavenge.go:400 +0x4b fp=0xc000055fa0 > sp=0xc000055f78 pc=0x41f44b > runtime.bgscavenge(0x0?) > /usr/local/go/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000055fc8 > sp=0xc000055fa0 pc=0x41fa25 > runtime.gcenable.func2() > /usr/local/go/src/runtime/mgc.go:179 +0x26 fp=0xc000055fe0 sp=0xc000055fc8 > pc=0x415f06 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000055fe8 > sp=0xc000055fe0 pc=0x45f4a1 > created by runtime.gcenable > /usr/local/go/src/runtime/mgc.go:179 +0xaa > > rax 0x17 > rbx 0x476413 > rcx 0x460c95 > rdx 0x17 > rdi 0x2 > rsi 0x476413 > rbp 0x7f18906b3ff0 > rsp 0x7f18906b3fd8 > r8 0xffffffff > r9 0x0 > r10 0x8 > r11 0x246 > r12 0xc000067c70 > r13 0x0 > r14 0x6cb760 > r15 0x0 > rip 0x45f342 > rflags 0x206 > cs 0x33 > fs 0x0 > gs 0x0 > ``` > > > > Crash(with thread's stack): > > ```go > fatal error: unexpected signal during runtime execution > [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4647a0] > > runtime stack: > runtime.throw({0x479118?, 0xffffffffffffffff?}) > /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0x7fff293551f0 > sp=0x7fff293551c0 pc=0x43417d > runtime.sigpanic() > /usr/local/go/src/runtime/signal_unix.go:825 +0x285 fp=0x7fff29355220 > sp=0x7fff293551f0 pc=0x4495a5 > > goroutine 1 [syscall]: > runtime.cgocall(0x464890, 0xc000067f60) > /usr/local/go/src/runtime/cgocall.go:157 +0x5c fp=0xc000067f38 > sp=0xc000067f00 pc=0x40465c > main._Cfunc_core_logic() > _cgo_gotypes.go:39 +0x45 fp=0xc000067f60 sp=0xc000067f38 pc=0x4646e5 > main.coreLogic() > /container_share/works/badstack/main.go:46 +0x17 fp=0xc000067f70 > sp=0xc000067f60 pc=0x464737 > main.main() > /container_share/works/badstack/main.go:51 +0x17 fp=0xc000067f80 > sp=0xc000067f70 pc=0x464777 > runtime.main() > /usr/local/go/src/runtime/proc.go:250 +0x1d3 fp=0xc000067fe0 > sp=0xc000067f80 pc=0x436913 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000067fe8 > sp=0xc000067fe0 pc=0x45f4a1 > > goroutine 2 [force gc (idle)]: > runtime.gopark(0x47a880, 0x6cb4d0, 0x11, 0x14, 0x1) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000054f88 > sp=0xc000054f58 pc=0x436dbd > runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000054fb8 > sp=0xc000054f88 pc=0x436e4a > runtime.forcegchelper() > /usr/local/go/src/runtime/proc.go:305 +0xb0 fp=0xc000054fe0 > sp=0xc000054fb8 pc=0x436b90 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000054fe8 > sp=0xc000054fe0 pc=0x45f4a1 > created by runtime.init.6 > /usr/local/go/src/runtime/proc.go:293 +0x25 > > goroutine 3 [GC sweep wait]: > runtime.gopark(0x47a880, 0x6cb640, 0xc, 0x14, 0x1) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055758 > sp=0xc000055728 pc=0x436dbd > runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055788 > sp=0xc000055758 pc=0x436e4a > runtime.bgsweep(0x0?) > /usr/local/go/src/runtime/mgcsweep.go:278 +0x98 fp=0xc0000557c8 > sp=0xc000055788 pc=0x421998 > runtime.gcenable.func1() > /usr/local/go/src/runtime/mgc.go:178 +0x26 fp=0xc0000557e0 sp=0xc0000557c8 > pc=0x415f66 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000557e8 > sp=0xc0000557e0 pc=0x45f4a1 > created by runtime.gcenable > /usr/local/go/src/runtime/mgc.go:178 +0x6b > > goroutine 4 [GC scavenge wait]: > runtime.gopark(0x47a880, 0x6cb6c0, 0xd, 0x14, 0x2) > /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055f48 > sp=0xc000055f18 pc=0x436dbd > runtime.goparkunlock(0x47caa0?, 0x1?, 0x0?, 0x0?) > /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055f78 > sp=0xc000055f48 pc=0x436e4a > runtime.(*scavengerState).park(0x6cb6c0) > /usr/local/go/src/runtime/mgcscavenge.go:400 +0x4b fp=0xc000055fa0 > sp=0xc000055f78 pc=0x41f44b > runtime.bgscavenge(0x0?) > /usr/local/go/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000055fc8 > sp=0xc000055fa0 pc=0x41fa25 > runtime.gcenable.func2() > /usr/local/go/src/runtime/mgc.go:179 +0x26 fp=0xc000055fe0 sp=0xc000055fc8 > pc=0x415f06 > runtime.goexit() > /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000055fe8 > sp=0xc000055fe0 pc=0x45f4a1 > created by runtime.gcenable > /usr/local/go/src/runtime/mgc.go:179 +0xaa > ``` > > > > GDB(with malloc stack): > > This will call into runtime.morestack_noctxt, and end up with badstack > since it's on g0's stack. > > ```c > (gdb) b runtime.sigpanic > Breakpoint 1 at 0x449320: file /usr/local/go/src/runtime/signal_unix.go, > line 822. > (gdb) r > Starting program: /container_share/works/badstack/main > [Thread debugging using libthread_db enabled] > Using host libthread_db library "/lib64/libthread_db.so.1". > [New Thread 0x7fffd05d3700 (LWP 213229)] > [New Thread 0x7fffcfdd2700 (LWP 213230)] > [New Thread 0x7fffcf5d1700 (LWP 213231)] > [New Thread 0x7fffcedd0700 (LWP 213232)] > [New Thread 0x7fffce58f700 (LWP 213233)] > [New Thread 0x7fffcdd8e700 (LWP 213234)] > > Thread 1 "main" received signal SIGSEGV, Segmentation fault. > 0x00000000004647a0 in core () at /container_share/works/badstack/main.go:18 > 18 *ptr = 1024; > (gdb) c > Continuing. > > Thread 1 "main" hit Breakpoint 1, runtime.sigpanic () at > /usr/local/go/src/runtime/signal_unix.go:822 > 822 func sigpanic() { > (gdb) p $rsp > $1 = (void *) 0x7fffcd58cfe8 > (gdb) x/x $r14+0x10 > 0x6cb770 <runtime.g0+16>: 0xff7fed70 > (gdb) c > Continuing. > fatal: morestack on g0 > ``` > > > > GDB(with thread's stack): > > This seems all working as expected. > > ```c > (gdb) b runtime.sigpanic > Breakpoint 1 at 0x449320: file /usr/local/go/src/runtime/signal_unix.go, > line 822. > (gdb) r > Starting program: /container_share/works/badstack/main > [Thread debugging using libthread_db enabled] > Using host libthread_db library "/lib64/libthread_db.so.1". > [New Thread 0x7fffd05d3700 (LWP 214288)] > [New Thread 0x7fffcfdd2700 (LWP 214289)] > [New Thread 0x7fffcf5d1700 (LWP 214290)] > [New Thread 0x7fffcedd0700 (LWP 214291)] > [New Thread 0x7fffce5cf700 (LWP 214292)] > > Thread 1 "main" received signal SIGSEGV, Segmentation fault. > 0x00000000004647a0 in core () at /container_share/works/badstack/main.go:18 > 18 *ptr = 1024; > (gdb) c > Continuing. > > Thread 1 "main" hit Breakpoint 1, runtime.sigpanic () at > /usr/local/go/src/runtime/signal_unix.go:822 > 822 func sigpanic() { > (gdb) p $rsp > $1 = (void *) 0x7fffffffd8e8 > (gdb) x/x $r14+0x10 > 0x6cb770 <runtime.g0+16>: 0xff7fed70 > (gdb) c > Continuing. > fatal error: unexpected signal during runtime execution > [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4647a0] > ``` > > > > ENV: > > ```makefile > ❯ clang -v > > clang version 16.0.6 (Red Hat 16.0.6-2.module_el8+588+6f71ce7b) > > ❯ gcc -v > > gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC) > > ❯ uname -a > Linux 6cc94b77abd7 6.4.16-orbstack-00103-g02b40eb69695 #1 SMP Wed Sep 13 > 10:13:30 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux > ``` > > > > Reproducer: > > compile with: `CC=clang CXX=clang++ CFLAGS="-g -O0" go build > -gcflags="all=-N -l" main.go` > > ```Go > package main > > /* > #include <stdio.h> > #include <stddef.h> > #include <ucontext.h> > #include <stdlib.h> > > static ucontext_t uctx_main, uctx_core; > > void core() > { > // core logic > > > // trigger crash > int* ptr = NULL; > *ptr = 1024; > } > > void core_logic() > { > size_t size = 1024 * 1024; > char stack[size]; // SIGSEGV > //void* stack = malloc(size); // SIGTRAP > > if (getcontext(&uctx_core) == -1) > printf("failed to getcontext"); > > uctx_core.uc_stack.ss_sp = stack; > uctx_core.uc_stack.ss_size = size; > uctx_core.uc_link = &uctx_main; > > makecontext(&uctx_core, core, 0); > > if (swapcontext(&uctx_main, &uctx_core) == -1) > printf("failed to swapcontext"); > > printf("back\n"); > } > */ > // #cgo CFLAGS: -g -O0 > import "C" > > func coreLogic() { > C.core_logic() > } > > func main() { > // Call the C function from Go > coreLogic() > } > ``` > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/50fc6c55-4ae1-401b-ae08-3a8f113f2ec6n%40googlegroups.com.