2

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

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

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

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

4

1 回答 1

3

In C++03

Note: exit() is a C function.

C as a language does not have the concept of threads at the language level.
Threads are usually added to C via a library support. So you need to read the library documentation of the affects of calling exit() from a thread that is not the main thread.

It is probably not portable across threading implementations.

Your best bet is to only call exit() from the main thread.
In a child thread you should probably just set some state that is viewed by the main thread. Let the main thread see this state and call exit manually. Note even calling exit on the man thread may hang some threading libraries if their are child threads still running. So best to get the main thread to wait for all children before exiting if you want your code to be portable.

In C++11

Now that C++11 has entered the since with explicit threading in the language there is more to it. See n3376 Section 18.4.1 [cstdint.syn] Paragraph 8

The function exit() has additional behavior in this International Standard:

— First, objects with thread storage duration and associated with the current thread are destroyed. Next, objects with static storage duration are destroyed and functions registered by calling atexit are called.

      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).

— Next, all open C streams (as mediated by the function signatures declared in ) with unwritten buffered data are flushed, all open C streams are closed, and all files created by calling tmpfile() are removed.

— Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

于 2012-07-10T02:48:59.930 回答