Cgo在返回Go Runtime之前在x_cgo_notify_runtime_init_done中被阻止

I am trying to write runc exec by myself, but got problems while implementing nsenter module.

Here is Sample Code:

package main
import "fmt"
/*
#define JUMP_PARENT 0x00
#define JUMP_CHILD  0xA0
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <setjmp.h>

char child_stack[4096] __attribute__ ((aligned(16)));

int child_func(void *arg) {
    jmp_buf* env  = (jmp_buf*)arg;
    longjmp(*env, JUMP_CHILD);
}

__attribute__((constructor)) void init(void) {
    printf("init...
");
    jmp_buf env;
    switch(setjmp(env)) {
        case JUMP_PARENT: 
        printf("JUMP_PARENT
");
            int child_pid = clone(child_func, child_stack, CLONE_PARENT, env);
            printf("CHILD_PID: %d
", child_pid);
            exit(0);
        case JUMP_CHILD:
            printf("JUMP_CHILD
");
            return;
    }
}
*/
import "C"

func main() {
    fmt.Println("main...")
}

Here is the output in CentOS7:

[root@localhost cgo-practive]# go build .
[root@localhost cgo-practive]# ls
cgo-practive  main.go
[root@localhost cgo-practive]# ./cgo-practive
init...
JUMP_PARENT
CHILD_PID: 14348
[root@localhost cgo-practive]# JUMP_CHILD
// program blocked here

Then I used gdb to find out the blocked reason:

(gdb) list
28              exit(0);
29          case JUMP_CHILD:
30              printf("JUMP_CHILD
");
31              return;
32      }
33  }
34  */
35  import "C"
36
37  func main() {
(gdb) info stack
#0  0x00007efd6f9684ed in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007efd6f966170 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#2  0x00000000004862e6 in x_cgo_notify_runtime_init_done (dummy=<optimized out>) at gcc_libinit.c:69
#3  0x0000000000451070 in runtime.asmcgocall () at /usr/local/go/src/runtime/asm_amd64.s:637
#4  0x00007ffdec4b5c30 in ?? ()
#5  0x000000000044efd1 in runtime.malg.func1 () at /usr/local/go/src/runtime/proc.go:3289
#6  0x000000000044f886 in runtime.systemstack () at /usr/local/go/src/runtime/asm_amd64.s:351
#7  0x000000000042c5b0 in ?? () at /usr/local/go/src/runtime/proc.go:1146
#8  0x000000000044f719 in runtime.rt0_go () at /usr/local/go/src/runtime/asm_amd64.s:201
#9  0x0000000000000000 in ?? ()

It seems that the program was blocked in x_cgo_notify_runtime_init_done, but I am not good at cgo, can't figure out why it was blocked.

Thanks.

1个回答

as man page says

Stacks grow downward on all processors that run Linux (except the HP PA processors), so child_stack usually points to the topmost address of the memory space set up for the child stack.

So you should use code below instead

int child_pid = clone(child_func, &child_stack[4096], CLONE_PARENT, &env);
doulan8054
doulan8054 它会覆盖数据段的其他部分,可能是Go运行时使用的某些变量。
一年多之前 回复
dtdh11647
dtdh11647 它有效,非常感谢。 但是我仍然不明白为什么堆栈指针错误会导致pthread_cond_broadcast阻塞?
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐