在 OSX Sierra 上分叉后使用 GLUT
Using GLUT after fork on OSX Sierra
在 Sierra 之前,我曾经能够在分叉原始进程后在子进程上初始化 GLUT。使用最新版本的 Sierra,这似乎已经改变。以下程序因分段错误而崩溃。如果我改为将所有过剩函数移至父进程,则一切正常。为什么使用 parent/child 过程会有区别?
#include <stdlib.h>
#include <GLUT/glut.h>
void pass(void){
}
int main(int argc, char* argv[]) {
pid_t childpid;
childpid = fork();
if (childpid == 0){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(100,100);
glutCreateWindow("test");
glutDisplayFunc(pass);
glGetError();
glutMainLoop();
}else{
sleep(5);
}
exit(1);
}
我得到的分段错误:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [0]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: _dispatch_main_queue_callback_4CF called from the wrong thread
crashed on child side of fork pre-exec
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libdispatch.dylib 0x00007fffe8e7bd21 _dispatch_main_queue_callback_4CF + 1291
1 com.apple.CoreFoundation 0x00007fffd3c7bbe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
2 com.apple.CoreFoundation 0x00007fffd3c3d00d __CFRunLoopRun + 2205
3 com.apple.CoreFoundation 0x00007fffd3c3c514 CFRunLoopRunSpecific + 420
4 com.apple.Foundation 0x00007fffd57e1c9b -[NSRunLoop(NSRunLoop) limitDateForMode:] + 196
5 com.apple.glut 0x0000000104f39e93 -[GLUTApplication run] + 321
6 com.apple.glut 0x0000000104f46b0e glutMainLoop + 279
7 a.out 0x0000000104f24ed9 main + 121 (main.c:18)
8 libdyld.dylib 0x00007fffe8ea4255 start + 1
fork()
不是创建线程,它是 forks 进程。在调用 fork 之后,您有两个进程具有几乎相同的地址 space 内容,但它们的地址 space 是相互保护的。关于 fork()
的一般规则是,在子进程中 fork 之后唯一明智的做法是用 execve()
替换进程映像;做任何其他事情都需要在程序设计中有很多先见之明。
线程的创建方式不同。我建议您使用您选择的编程语言提供的实际线程原语。
也就是说,许多操作系统和 GUI 库希望进程的 GUI 部分在主线程中 运行,因此这也可能是部分原因。还要注意 OpenGL 和多线程有点挑剔。
在 Sierra 之前,我曾经能够在分叉原始进程后在子进程上初始化 GLUT。使用最新版本的 Sierra,这似乎已经改变。以下程序因分段错误而崩溃。如果我改为将所有过剩函数移至父进程,则一切正常。为什么使用 parent/child 过程会有区别?
#include <stdlib.h>
#include <GLUT/glut.h>
void pass(void){
}
int main(int argc, char* argv[]) {
pid_t childpid;
childpid = fork();
if (childpid == 0){
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(100,100);
glutCreateWindow("test");
glutDisplayFunc(pass);
glGetError();
glutMainLoop();
}else{
sleep(5);
}
exit(1);
}
我得到的分段错误:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [0]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: _dispatch_main_queue_callback_4CF called from the wrong thread
crashed on child side of fork pre-exec
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libdispatch.dylib 0x00007fffe8e7bd21 _dispatch_main_queue_callback_4CF + 1291
1 com.apple.CoreFoundation 0x00007fffd3c7bbe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
2 com.apple.CoreFoundation 0x00007fffd3c3d00d __CFRunLoopRun + 2205
3 com.apple.CoreFoundation 0x00007fffd3c3c514 CFRunLoopRunSpecific + 420
4 com.apple.Foundation 0x00007fffd57e1c9b -[NSRunLoop(NSRunLoop) limitDateForMode:] + 196
5 com.apple.glut 0x0000000104f39e93 -[GLUTApplication run] + 321
6 com.apple.glut 0x0000000104f46b0e glutMainLoop + 279
7 a.out 0x0000000104f24ed9 main + 121 (main.c:18)
8 libdyld.dylib 0x00007fffe8ea4255 start + 1
fork()
不是创建线程,它是 forks 进程。在调用 fork 之后,您有两个进程具有几乎相同的地址 space 内容,但它们的地址 space 是相互保护的。关于 fork()
的一般规则是,在子进程中 fork 之后唯一明智的做法是用 execve()
替换进程映像;做任何其他事情都需要在程序设计中有很多先见之明。
线程的创建方式不同。我建议您使用您选择的编程语言提供的实际线程原语。
也就是说,许多操作系统和 GUI 库希望进程的 GUI 部分在主线程中 运行,因此这也可能是部分原因。还要注意 OpenGL 和多线程有点挑剔。