Linux C++:main() 返回是否会导致多线程应用程序终止?

发布于 2024-09-10 17:39:09 字数 443 浏览 3 评论 0原文

这个问题看起来可能是重复的,但我找不到。如果我错过了之前的问题,抱歉。

在 Java 中,我有大部分经验,如果你的 main() 分叉一个线程并立即返回,进程将继续运行,直到进程中的所有(非守护进程)线程都停止。

在 C++ 中,情况似乎并非如此 - 一旦主线程返回,进程就会终止,而其他线程仍在运行。对于我当前的应用程序,可以通过应用 pthread_join() 轻松解决这个问题,但我想知道是什么导致了这种行为。这个编译器 (gcc) 是特定的、pthreads 特定的,还是在大多数/所有已实现 C++ 的平台上共享的行为?这种行为是否可以在 pthreads 中配置(我已经查看了 pthread_attr_*() 函数中的 pthread api,但没有看到任何看起来相关的内容。)?

完全独立的问题,但是当你在这里时......人们会使用 pthread_detatch() 做什么?

This question seems like it's probably a duplicate, but I was unable to find one. If I missed a previous question, apologies.

In Java, where I have most of my experience, if your main() forks a thread and immediately returns the process continues to run until all (non-daemon) threads in the process have stopped.

In C++, this appears not to be the case - as soon as the main thread returns the process is terminating with other threads still running. For my current app this is easily solved with the application of pthread_join() but I'm wondering what causes this behavior. Is this compiler (gcc) specific, pthreads specific, or is kind of behavior shared across most/all platforms for which C++ has been implemented? Is this behavior configurable within pthreads (I've looked through the pthread api at the pthread_attr_*() functions and didn't see anything that looked relevant.)?

Completely separate question, but while you're here ... what would one use pthread_detatch() for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

○愚か者の日 2024-09-17 17:39:09

是的。在现代Linux(更重要的是GNU libc的较新版本)中,exit_group是main返回时使用的系统调用,而不是普通的exitexit_group 描述如下:

这个系统调用相当于
exit(2) 除非它终止
仅调用线程,但所有
调用进程中的线程
线程组。

值得注意的是,当前的 C++ 标准没有提及线程,因此此行为不是 C++ 特定的,而是特定于您的特定实现的。也就是说,我个人见过的每个实现都会在主线程终止时杀死所有线程。

编辑: 还值得注意的是 Jonathan Leffler 的回答,它指出 POSIX 标准确实指定了这种行为,因此对于使用 pthreads 进行线程处理的应用程序来说这当然是正常的。

编辑:回答有关pthread_detach的后续问题。基本上,如果您不加入非分离线程,则被认为是资源泄漏。如果您有一个长时间运行的任务,不需要“等待”,并且它只是“结束时结束”,那么您应该分离它,当它在没有连接的情况下终止时,不会出现资源泄漏。手册页内容如下:

pthread_detach()函数标记
线程标识为
超然的。当一个分离的线程
终止,其资源为
自动释放回
无需另一个系统
加入已终止的线程
线程。

因此,一个快速而肮脏的答案是:“当你不关心它何时结束时,将其分离。如果另一个线程关心它何时结束并且必须等待它终止,那么就不要这样做。”

Yes. In modern linux (more importantly newer versions of GNU libc) exit_group is the system call used when main returns, not plain exit. exit_group is described as follows:

This system call is equivalent to
exit(2) except that it terminates not
only the calling thread, but all
threads in the calling process's
thread group.

It is worth noting that current the c++ standard makes no mention of threads, so this behavior is not c++ specific, but instead is specific to your particular implementation. That said, every implementation I've personally seen kills all threads when the main thread terminates.

EDIT: It is also worth noting Jonathan Leffler's answer which points out that the POSIX standard does indeed specify this behavior, so it is certainly normal for an application using pthreads for its threading.

EDIT: To answer the follow up about pthread_detach. Basically it is considered a resource leak if you do not join a non-detached thread. If you have a long running task which you have no need to "wait for", and it just "ends when it ends" then you should detach it which will not have a resource leak when it terminates with no join. The man page says the following:

The pthread_detach() function marks
the thread identified by thread as
detached. When a detached thread
terminates, its resources are
automatically released back to the
system without the need for another
thread to join with the terminated
thread.

So a quick and dirty answer is: "when you don't care when it ends, detach it. If another thread cares when it ends and must wait for it to terminate, then don't."

红颜悴 2024-09-17 17:39:09

是的

POSIX 标准表示:

§3.297 进程终止

进程终止有两种:

  1. 当使用 exit()、_exit() 或 _Exit() 函数请求时,通过从 main() 返回来正常终止;或者当进程中的最后一个线程通过从其启动函数返回、调用 pthread_exit() 函数或通过取消而终止时。

  2. 当 abort() 函数请求或收到某些信号时,会发生异常终止。

第一个正常终止条件适用。 (请注意,C++ (1998, 2003) 标准没有提及线程。)


关于 pthread_detach()

POSIX 标准(再次)说:

pthread_detach() 函数应向实现指示线程终止时可以回收该线程的存储。如果线程尚未终止,pthread_detach() 不应导致其终止。

理由是:

最终应该为创建的每个线程调用 pthread_join() 或 pthread_detach() 函数,以便回收与线程关联的存储。

有人建议“分离”功能不是必需的; detachstate 线程创建属性就足够了,因为线程永远不需要动态分离。然而,至少在两种情况下会出现这种需要:

  1. 在 pthread_join() 的取消处理程序中,几乎必须有一个 pthread_detach() 函数,以便分离 pthread_join() 正在等待的线程。如果没有它,则需要让处理程序执行另一个 pthread_join() 来尝试分离线程,这会无限期地延迟取消处理,并引入对 pthread_join() 的新调用,这本身可能需要取消处理程序。在这种情况下,动态分离几乎是必不可少的。

  2. 为了分离“初始线程”(这在设置服务器线程的进程中可能是需要的)。

Yes

The POSIX standard says:

§3.297 Process Termination

There are two kinds of process termination:

  1. Normal termination occurs by a return from main(), when requested with the exit(), _exit(), or _Exit() functions; or when the last thread in the process terminates by returning from its start function, by calling the pthread_exit() function, or through cancellation.

  2. Abnormal termination occurs when requested by the abort() function or when some signals are received.

The first normal termination condition applies. (Note that the C++ (1998, 2003) standard says nothing about threads.)


Regarding pthread_detach()

The POSIX standard (again) says:

The pthread_detach() function shall indicate to the implementation that storage for the thread thread can be reclaimed when that thread terminates. If thread has not terminated, pthread_detach() shall not cause it to terminate.

And the rationale says:

The pthread_join() or pthread_detach() functions should eventually be called for every thread that is created so that storage associated with the thread may be reclaimed.

It has been suggested that a "detach" function is not necessary; the detachstate thread creation attribute is sufficient, since a thread need never be dynamically detached. However, need arises in at least two cases:

  1. In a cancellation handler for a pthread_join() it is nearly essential to have a pthread_detach() function in order to detach the thread on which pthread_join() was waiting. Without it, it would be necessary to have the handler do another pthread_join() to attempt to detach the thread, which would both delay the cancellation processing for an unbounded period and introduce a new call to pthread_join(), which might itself need a cancellation handler. A dynamic detach is nearly essential in this case.

  2. In order to detach the "initial thread" (as may be desirable in processes that set up server threads).

听不够的曲调 2024-09-17 17:39:09

这不是特定于编译器的,而是标准行为;当 main() 退出时,应用程序将终止,因此如果您想防止应用程序终止,则需要 main() 阻塞,直到所有线程都终止,您可以通过加入这些线程来完成此操作。当您调用 pthread_create 时,它​​会为该线程分配资源。除非您执行 pthread_join(它会阻塞直到线程终止)或 pthread_detach(这会导致线程在退出时自动释放资源),否则不会释放资源。每当您启动一个后台线程时,您都应该使用 pthread_detach ,该线程将在其任务完成时终止并且您不需要等待。

为了使这一点更加具体,假设您有多个线程执行一部分计算,然后以某种方式聚合结果。在这种情况下,您将使用 join,因为您需要线程的结果才能继续。现在,考虑这样一种情况:线程侦听套接字并处理传入请求,直到标志指示该线程应退出。在这种情况下,您将使用 pthread_detach,因为没有任何事情需要线程终止才能继续,因此与该线程关联的资源应该自动消失。

This is not compiler specific and is standard behavior; the application terminates when main() exits, so if you want to prevent the application from terminating, you need main() to block until all threads have terminated, which you do by joining those threads. When you invoke pthread_create, it allocates resources for that thread. The resources are not deallocated unless you do a pthread_join (which blocks until the thread terminates) or pthread_detach (which causes the thread to automatically release resources when that thread exits). You should use pthread_detach whenever you launch a background thread that will terminate when its task is completed and for which you do not need to wait.

To make this a little bit more concrete, suppose you have several threads that perform a piece of a computation, and then you aggregate the result in some way. That would be a case where you would use join, because you need the results of the threads to proceed. Now, consider a case where a thread listens on a socket and processes incoming requests, until a flag indicates that the thread should quit. In this case, you would use pthread_detach, since nothing needs the thread to terminate in order to proceed, and so the resources associated with that thread should go away automatically.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文