我正在使用FreeGLUT在Linux上开发一个多线程C ++应用程序。奇怪的是,在我的一个线程中调用exit()会导致调用并完成onexit()回调,但无法退出程序。相反,根据GDB,它会挂起在GLUT库中的select()调用中。
当我按'q'时,我还有一个键盘回调退出。如果我在程序挂起时按'q',则GLUT退出。
似乎没有人遇到类似的问题。文档说exit()应该关闭整个进程,而不仅仅是一个线程,所以不是这样。我很难过。你有什么想法吗?
编辑:我发现了问题。退出处理程序完成后我错了。库函数调用正在等待调用exit()时已锁定的互斥锁。 GLUT只是利用了空闲时间。谢谢大家的回复。答案 0 :(得分:3)
注意:exit()是一个C函数。
作为一种语言的C语言在语言层面没有线程的概念 线程通常通过库支持添加到C中。所以你需要从不是主线程的线程中读取调用exit()的影响的库文档。它可能无法在线程实现中移植。
最好的办法是只从主线程中调用exit() 在子线程中,您可能只需设置主线程查看的某个状态。让主线程看到此状态并手动调用exit。注意即使在man线程上调用exit,如果它们的子线程仍在运行,也可能会挂起一些线程库。因此,如果您希望代码可以移植,那么最好让主线程在退出之前等待所有孩子。
现在C ++ 11已经进入了该语言,并且语言中有明确的线程。 See n3376 Section 18.4.1 [cstdint.syn] Paragraph 8
函数exit()在本国际标准中有其他行为:
- 首先,销毁具有线程存储持续时间并与当前线程关联的对象。接下来,销毁具有静态存储持续时间的对象,并调用通过调用atexit注册的函数。
See 3.6.3 for the order of destructions and calls. (Automatic objects are not destroyed as a result of calling exit().) If control leaves a registered function called by exit because the function does not provide a handler for a thrown exception, std::terminate() shall be called (15.5.1).
- 接下来,刷新所有打开的C流(由声明的函数签名调解)和未写入的缓冲数据,关闭所有打开的C流,并删除通过调用tmpfile()创建的所有文件。
- 最后,控制权返回给主机环境。如果status为零或EXIT_SUCCESS,则返回状态成功终止的实现定义形式。如果status为EXIT_FAILURE,则返回状态为不成功终止的实现定义形式。否则返回的状态是实现定义的。