16

当我从 调用pthread_exitmain,程序永远不会终止。我希望程序完成,因为我正在退出程序的唯一线程,但它不起作用。好像挂了

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int main(int argc, char *argv[])
{
    printf("-one-\n");

    pthread_exit(NULL);

    printf("-two-\n");
}

Process Explorer显示(唯一)线程处于Wait:DelayExecution状态。

根据pthread_exit文档:

在最后一个线程终止后,该进程应以退出状态 0 退出。行为应该就像调用 exit() 的实现,在线程终止时使用零参数。

我正在使用Dev-C++ v4.9.9.2pthreads-win32 v2.8.0.0(链接到libpthreadGC2.a)。

该库似乎还可以(例如,调用pthread_selfpthread_createmain工作正常)。

pthread_exit我不应该打电话给我有什么理由main吗?

4

4 回答 4

18

那么它在 pthreads 的 linux 实现中绝对是合法的,请参阅 pthreads_exit 中的注释部分。它指出

为了允许其他线程继续执行,主线程应该通过调用 pthread_exit() 而不是 exit(3) 来终止。

此外,查看这里的源代码(torwads end)表明它大致转换为 _endthread 或 _endthreadex。这里的文档没有提到不在初始线程中调用它。

于 2010-08-24T18:42:49.530 回答
15

这是完全合法和预期的行为。整个过程仅在所有线程终止或exit显式或隐式调用时结束。

正常的 return frommain相当于调用exit. 如果您mainpthread_exit您的结尾明确表示您希望其他线程继续。

于 2010-08-24T19:42:49.020 回答
4

在 main 中使用 pthread_exit 很好。当使用 pthread_exit 时,主线程将停止执行并保持僵尸(已失效)状态,直到所有其他线程退出。

如果您在主线程中使用 pthread_exit,则无法获取其他线程的返回状态并且无法对其他线程进行清理(可以使用 pthread_join(3) 完成)。此外,最好分离线程(pthread_detach(3)),以便在线程终止时自动释放线程资源。在所有线程退出之前,共享资源不会被释放。

在主线程不分配资源时可以使用,不需要清理。下面的代码显示了在主线程中使用 pthread_exit。main 中的第二个 printf 不会打印,因为调用 pthread_exit 后主线程退出。Ps 输出显示了已失效的主线程。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

void *functionC(void *);

int main()
{
        int rc;
        pthread_t th;

        if(rc = pthread_create(&th, NULL, &functionC, NULL))
        {
                printf("Thread creation failed, return code %d, errno %d", rc,                 errno);
        }

        printf("Main thread %lu: Sleeping for 20 seconds\n", pthread_self());
        fflush(stdout);
        sleep(20);
        pthread_exit(NULL);
        printf("Main thread %lu: This will not be printed as we already called         pthread_exit\n", pthread_self());
        exit(0);
}

void *functionC(void *)
{
        printf("Thread %lu: Sleeping for 20 second\n", pthread_self());
        sleep(20);
        printf("Thread %lu: Came out of first and sleeping again\n", pthread_self());
        sleep(20);
        printf("CThread %lu: Came out of second sleep\n", pthread_self());
}

上述代码的输出:

Main thread 140166909204288: Sleeping for 20 seconds
Thread 140166900684544: Sleeping for 20 second
Thread 140166900684544: Came out of first and sleeping again
CThread 140166900684544: Came out of second sleep

ps输出:

root@xxxx-VirtualBox:~/pthread_tst# ps -elfT |grep a.out
0 S root      9530  9530  9496  0  80   0 -  3722 hrtime 17:31 pts/1    00:00:00 ./a.out
1 S root      9530  9531  9496  0  80   0 -  3722 hrtime 17:31 pts/1    00:00:00 ./a.out
0 S root      9537  9537  2182  0  80   0 -  5384 pipe_w 17:31 pts/0    00:00:00 grep --color=auto a.out

root@xxxx-VirtualBox:~/pthread_tst# ps -elfT |grep a.out
0 Z root      9530  9530  9496  0  80   0 -     0 -      17:31 pts/1    00:00:00 [a.out] <defunct>
1 S root      9530  9531  9496  0  80   0 -  4258 hrtime 17:31 pts/1    00:00:00 ./a.out
0 S root      9539  9539  2182  0  80   0 -  5384 pipe_w 17:31 pts/0    00:00:00 grep     --color=auto a.out`

有关线程的更多信息,请查看博客Tech Easy

于 2018-09-25T05:56:12.537 回答
1

在 Linux(CentOS Linux 版本 7.2.1511(Core))上进行测试时,我发现主程序确实在等待“子”线程继续。我也无法从 main 传递返回代码,尽管它可以指定为 pthread_exit() 的参数,正如 Raul 上面所说的,它总是返回退出代码 0:

retval=3;
pthread_exit(&retval);

在使用 Clang 编译器(版本 3.4.2)和 sanitizer 选项时,我们还观察到一条错误消息:

==5811==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7f4c090321d0 in thread T0
#0 0x7f4c08be3e29 in __interceptor_free (/home/karstenburger/tests/libc/pthread_exit_in_main/a+0x65e29)
#1 0x7f4c08333358 in free_key_mem (/lib64/libdl.so.2+0x1358)
#2 0x7f4c08745bc1 in __nptl_deallocate_tsd (/lib64/libpthread.so.0+0x7bc1)
#3 0x7f4c07771b38 in __libc_start_main (/lib64/libc.so.6+0x21b38)
#4 0x7f4c08bfa08c in _start (/home/karstenburger/tests/libc/pthread_exit_in_main/a+0x7c08c)

AddressSanitizer can not describe address in more detail (wild memory access suspected).
SUMMARY: AddressSanitizer: bad-free ??:0 __interceptor_free
==5811==ABORTING
于 2016-11-25T09:36:15.677 回答