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.

Reply via email to