从main调用pthread_exit可以吗?

时间:2010-08-24 17:55:59

标签: c winapi pthreads exit main

当我从pthread_exit拨打main时,程序永远不会终止。我期望程序完成,因为我退出程序的唯一线程,但它不起作用。它好像挂了。

#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.2 pthreads-win32 v2.8.0.0 (链接libpthreadGC2.a)。

库似乎没问题(例如,从pthread_self调用pthread_createmain可以正常工作。

我是否应该从pthread_exit拨打main来解决问题?

4 个答案:

答案 0 :(得分:16)

它在pthreads的linux实现中绝对合法,请参阅pthreads_exit中的注释部分。它声明

  

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

此外,查看源代码here(转发结尾)显示它大致转换为_endthread或_endthreadex。文档here没有提及在初始线程中没有调用它。

答案 1 :(得分:15)

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

main的正常回报相当于对exit的回复。如果您使用main结束pthread_exit,则明确表示您希望其他主题继续。

答案 2 :(得分:3)

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

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

在主线程中不分配资源时也可以使用,不需要清理。下面的代码显示在主线程中使用pthread_exit。由于调用pthread_exit后主线程退出,因此不会打印main中的第二个printf。 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,以获取有关线程的更多信息。

答案 3 :(得分:1)

在Linux上测试时(CentOS Linux版本7.2.1511(核心版))我发现主程序确实等待了#34; child&#34;线程继续。 此外,我无法从main传递返回代码,虽然它可以指定为pthread_exit()的参数,因为Raul上面说它总是以退出代码0返回:

retval=3;
pthread_exit(&retval);

使用Clang编译器(版本3.4.2)和清洁剂选项时,我们也发现了一条错误消息:

==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