When the main thread exits, do other threads also exit?
Asked Answered
S

4

33

I have a problem about main threads and other threads in the same process. When the main function returns, do the other threads exit too? I am confused about this.

Consider the following test code:

void* test1(void *arg)
{
    unsigned int i = 0;
    while (1){
        i+=1;
    }
    return NULL;
}

void* test2(void *arg)
{
    long double i = 1.0;
    while (1){
        i *= 1.1;
    }
    return NULL;
}

void startThread ( void * (*run)(void*), void *arg) {
  pthread_t t;
  pthread_attr_t attr;
  if (pthread_attr_init(&attr) != 0
      || pthread_create(&t, &attr, run, arg) != 0
      || pthread_attr_destroy(&attr) != 0
      || pthread_detach(t) != 0) {
    printf("Unable to launch a thread\n");
    exit(1);
  }
}

int main()
{
    startThread(test1, NULL);
    startThread(test2, NULL);

    sleep(4);
    printf("main thread return.\n");

    return 0;
}

When the "main thread return." prints out, thread test1 and test2 also exit, can anyone tell me why?

Shwalb answered 9/8, 2012 at 2:28 Comment(1)
The text of the question doesn't match the question body. Is this about what happens when the main thread exits? Or is this about what happens when the main thread returns from the main function? (Obviously, the thread can't return if it exits. It can do one or the other.)Tallyho
T
30

When the main thread returns (i.e., you return from the main function), it terminates the entire process. This includes all other threads. The same thing happens when you call exit. You can avoid this by calling pthread_exit.

The purpose of pthread_detach is to make it so you don't need to join with other threads in order to release their resources. Detaching a thread does not make it exist past process termination, it will still be destroyed along with all the other threads.

Thyestes answered 9/8, 2012 at 2:41 Comment(4)
This answer as written is not true. When the main thread (or any thread) calls exit, or when the initial invocation of main returns, the entire process exits. But the main thread can exit with pthread_exit without affecting other threads.Pone
@R.. Does it mean that it is possible for a process to exit, but its threads continue execution?Maritime
@hsalimi: It is not possible for threads to continue after the process has exited. R is saying that is possible for the main thread to exit through pthread_exit with other threads continuing.Thyestes
@hsalimi: No. Threads are part of the process. If the process exits, they (along with all other process resources) cease to exist. Termination of the initial thread via pthread_exit does not cause the process to exit.Pone
M
31

You should use pthread_join() on each of the new threads, to inform the calling thread to wait on the sub-threads, suspending execution - and process exit - until those threads terminate.

Calling pthread_detach on the created threads won't keep them around after a process exits. From the linux man page:

The detached attribute merely determines the behavior of the system when the thread terminates; it does not prevent the thread from being terminated if the process terminates using exit(3) (or equivalently, if the main thread returns).

You'll sometimes see a pthread_exit in main used instead of explicit pthread_join calls, the intent being that exiting main in this way will allow other threads to continue running. In fact, the linux man page states this explicitly:

To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3).

But I don't know if this is expected behavior on all platforms, and I've always stuck to using pthread_join.

pthread_join requires the pthread_t for the target thread, so your code will need to change a bit since you need to create both threads before calling pthread_join to wait for them both. So you can't call it in startThread. You'll need to return a pthread_t, or pass a pointer to a pthread_t to your startThread function.

Matriarch answered 9/8, 2012 at 2:31 Comment(2)
Read the docs for pthread_detach carefully. It doesn't do what you seem to think.Matriarch
@Shwalb Maybe you are mistaking detach with the functionality provided e. g. in Java/C#/Python/etc. - daemon threads. Java internally keeps the process alive while any non-daemon threads are left alive (even though the main thread dies).Moratorium
T
30

When the main thread returns (i.e., you return from the main function), it terminates the entire process. This includes all other threads. The same thing happens when you call exit. You can avoid this by calling pthread_exit.

The purpose of pthread_detach is to make it so you don't need to join with other threads in order to release their resources. Detaching a thread does not make it exist past process termination, it will still be destroyed along with all the other threads.

Thyestes answered 9/8, 2012 at 2:41 Comment(4)
This answer as written is not true. When the main thread (or any thread) calls exit, or when the initial invocation of main returns, the entire process exits. But the main thread can exit with pthread_exit without affecting other threads.Pone
@R.. Does it mean that it is possible for a process to exit, but its threads continue execution?Maritime
@hsalimi: It is not possible for threads to continue after the process has exited. R is saying that is possible for the main thread to exit through pthread_exit with other threads continuing.Thyestes
@hsalimi: No. Threads are part of the process. If the process exits, they (along with all other process resources) cease to exist. Termination of the initial thread via pthread_exit does not cause the process to exit.Pone
R
1

All the threads in your process will be terminated when you return from main().

The libc library is the one responsible for implementing this behavior by calling exit() when the main() function returns. In turn, the exit() function will end up calling a thin-wrapper function named _exit() which (starting from libc v2.3) will finally invoke the exit_group system call and end up your process and also terminate all its threads.

This last system call is the one responsible for the behavior you noticed.

We can see this subtle note in the _exit() manual here:

C library/kernel differences
       In glibc up to version 2.3, the _exit() wrapper function invoked
       the kernel system call of the same name.  Since glibc 2.3, the
       wrapper function invokes exit_group(2), in order to terminate all
       of the threads in a process.

If your intention is to avoid this behavior, the only option is to call pthread_exit which will end your main thread and prevent you from returning to the libc's __libc_start_main() function.

Russophobe answered 15/7, 2021 at 16:9 Comment(0)
G
-1

As an aside on the same subject, I'd like to point out what seems to me an inaccuracy in the 3rd edition of APUE (Stevens & Rago). In section 7.3 it says "Normal termination occurs in five ways" and, among them it puts "Calling pthread_exit (Section 11.5) from the last thread". It seems to me that this is not true, because either main is still running (and pthread_exit doesn't terminate the program since main will do that) or main has already returned, so terminating the program, as this article correctly states.

Gleeful answered 25/10, 2023 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.