我一直在用 C/C++ 开发 webrtc 数据通道库写了一个程序 https://github.com/hamon-in/librtcdcpp/blob/alpine-test/examples/websocket_client/2in1.c在 C 中:
- 从同一进程创建两个对等点。
- 建立它们之间的联系。
- 如果成功则关闭连接。
在 debian docker 容器和我的主机 opensuse tumbleweed (所有 x86_64 和 64 位)上一切都运行良好,但在 alpine linux 容器(64 位 x86_64)上,我在子进程内收到 SEGFAULT:
上面的函数来自程序的依赖项“libnice”。看起来 *agent == NULL 并且无法在caller's https://github.com/libnice/libnice/blob/fb2f1f77a31baa91968fc81c205f980b6913f403/agent/conncheck.c#L1893-L1916范围。我什至插入了一个printf("Argument is %p", agent);
就在函数调用之前,它打印出它的内存,我可以验证它不为空。从反汇编来看,将代理的内容 (0x557a1d20) 复制为被调用者堆栈中的局部变量会导致段错误。即使在经过一段时间后,段错误也始终会发生在此时make clean
和重新编译。激活记录失败?堆栈腐败?
UPDATE: I made a more lightweight container and ran it, and now it segfaults at a different place in that same priv_conn_keepalive_tick_unlocked
. The argument seems to be set though (Notice the 0x7ffff7f9ad08):
因为我以为我可能会击中自由音乐的 https://wiki.musl-libc.org/functional-differences-from-glibc.html默认堆栈限制为 80k,我使用过getrlimit(RLIMIT_STACK, &rl)
获取堆栈大小,看起来已经是 8 MB 而不是 80k。进一步增加此限制似乎没有任何区别,除了如果我分配超过 8 MB,我的程序会提前崩溃insideGDB。 Gdb 说它收到一个未知信号“??”;在 gdb 之外,它会在没有改变堆栈大小的情况下正常崩溃的正常点崩溃。
我不确定问题到底是什么(堆栈损坏?)以及下一步要做什么来解决这个问题。
这是我的程序流程:
对于创建的每个同级,都有一个孩子process是用 fork() 创建的。父 子通信由 ZeroMQ 完成,我使用协议缓冲区将子内部触发的任何回调(及其参数)转发到父进程中运行的事件循环上。
所以对于上面的程序,有2个子进程和1个父进程。
重现步骤:
- 源文件:https://github.com/hamon-in/librtcdcpp/blob/alpine-test/examples/websocket_client/2in1.c https://github.com/hamon-in/librtcdcpp/blob/alpine-test/examples/websocket_client/2in1.c
- 高山码头集装箱:https://github.com/hamon-in/librtcdcpp/blob/alpine-test/Dockerfile.amd64 https://github.com/hamon-in/librtcdcpp/blob/alpine-test/Dockerfile.amd64
- 运行容器,二进制文件位于
/psl-librtcdcpp/examples/websocket_client/2in1
- 2in1 将产生两个子进程,这两个进程都会崩溃。