【问题标题】:exit() function fails to exit processexit() 函数无法退出进程
【发布时间】:2012-07-09 11:14:54
【问题描述】:

我正在使用 FreeGLUT 在 Linux 中开发一个多线程 C++ 应用程序。奇怪的是,在我的一个线程中调用 exit() 会导致调用并完成 onexit() 回调,但无法退出我的程序。根据 GDB,它会挂在 GLUT 库中的 select() 调用中。

我还有一个键盘回调,当我按“q”时退出。如果我在程序挂起时按“q”,GLUT 会正常退出。

似乎没有人遇到类似的问题。文档说 exit() 应该关闭整个进程,而不仅仅是一个线程,所以不是那样的。我难住了。你有什么想法吗?

编辑:我发现了问题。我错了退出处理程序已经完成。一个库函数调用正在等待一个在调用 exit() 时已经锁定的互斥锁。 GLUT 只是利用了空闲时间。谢谢大家的回复。

【问题讨论】:

  • 显示一些代码,或者我们所能做的就是猜猜哪里出了问题。
  • 创建显示此行为的最小可编译示例并发布。
  • while (true) { } 放入静态析构函数可能会有效地完成同样的事情。你有回溯,这意味着你已经成功了一半。您的代码的哪一部分调用了 GLUT?也许你应该戳一些信号量或信号来通知系统的其余部分是时候离开了。
  • exit() 文档是在没有线程概念的情况下编写的(因为 C 在语言级别没有线程的概念)。在 C 中,您可以在其中找到 exit() 线程的文档是通过外部库添加的。因此,您需要阅读线程库文档,了解当您从不是原始进程线程的线程调用 exit() 时会发生什么。它可能不便携。

标签: c++ linux glut exit freeglut


【解决方案1】:

在 C++03 中

注意:exit() 是一个 C 函数。

C 作为一种语言在语言级别没有线程的概念。
线程通常通过库支持添加到 C 中。因此,您需要阅读有关从不是主线程的线程调用 exit() 的影响的库文档。

它可能无法跨线程实现移植。

最好的办法是只从主线程调用 exit()。
在子线程中,您可能应该只设置一些由主线程查看的状态。让主线程看到这个状态并手动调用exit。请注意,即使在人线程上调用 exit 也可能会挂起一些线程库,如果它们的子线程仍在运行。因此,如果您希望代码可移植,最好让主线程在退出之前等待所有子线程。

在 C++11 中

既然 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() 创建的文件都被删除。

——最后,控制权返回到宿主环境。如果状态为零或 EXIT_SUCCESS,则返回状态成功终止的实现定义形式。如果状态为 EXIT_FAILURE,则返回状态未成功终止的实现定义形式。否则返回的状态是实现定义的。

【讨论】:

    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多