简体   繁体   English

g++ 和 gcc 在 pthread_cleanup_push/pop 上的行为不同

[英]g++ and gcc behave differently on pthread_cleanup_push/pop

This is my code这是我的代码

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

void cleanup(void *arg) {
    printf("cleanup: %s\n", (const char*)arg);
}

void *thr_fn1(void *arg) {
    printf("thread 1 strat\n");
    pthread_cleanup_push(cleanup, (void*)"thread 1 first handler");
    pthread_cleanup_push(cleanup, (void*)"thread 1 first handler");

    if(arg)
        return (void*)1;

    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);

    return (void*)1;
}

void *thr_fn2(void *arg) {
    printf("thread 2 strat\n");
    pthread_cleanup_push(cleanup, (void*)"thread 2 first handler");
    pthread_cleanup_push(cleanup, (void*)"thread 2 first handler");

    if(arg)
        return (void*)2;

    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);

    return (void*)2;
}

int main() {
    int err;
    pthread_t tid1, tid2;
    void *tret;

    pthread_create(&tid1, NULL, thr_fn1, (void*)1);
    pthread_create(&tid2, NULL, thr_fn2, (void*)1);

    pthread_join(tid1, &tret);
    printf("pthread 1 exit code %ld\n", tret);
    pthread_join(tid2, &tret);
    printf("pthread 2 exit code %ld\n", tret);

    return 0;
}

Now I run it using gcc and g++现在我使用gccg++运行它

$ gcc main.c -o main
$ ./main
thread 2 strat
thread 1 strat
pthread 1 exit code 1
pthread 2 exit code 2
$ g++ main.c -o main
$ ./main
thread 1 strat
cleanup: thread 1 first handler
cleanup: thread 1 first handler
thread 2 strat
cleanup: thread 2 first handler
cleanup: thread 2 first handler
pthread 1 exit code 1
pthread 2 exit code 2
$ 
  1. Why they behave differently?为什么他们的行为不同?
  2. Any other functions behave like this?还有其他功能是这样的吗?
  3. I found the implementations of gcc and g++ are different.我发现gccg++的实现是不同的。 So which one is a better implementation?那么哪个是更好的实现呢?

On Linux, the pthread_cleanup_push() and pthread_cleanup_pop() functions are implemented as macros that expand to text containing { and } , respectively.在 Linux 上, pthread_cleanup_push()pthread_cleanup_pop()函数实现为分别扩展为包含{}的文本的宏。

#  define pthread_cleanup_push(routine, arg) \
  do {                                       \
    __pthread_cleanup_class __clframe (routine, arg)

If compiled with g++, __pthread_cleanup_class is a C++ class:如果用__pthread_cleanup_class编译,__pthread_cleanup_class 是一个 C++ class:

#ifdef __cplusplus
/* Class to handle cancellation handler invocation.  */
class __pthread_cleanup_class
{
  void (*__cancel_routine) (void *);
  void *__cancel_arg;
  int __do_it;
  int __cancel_type;

 public:
  __pthread_cleanup_class (void (*__fct) (void *), void *__arg)
    : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
  ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
  void __setdoit (int __newval) { __do_it = __newval; }
  void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
                                           &__cancel_type); }
  void __restore () const { pthread_setcanceltype (__cancel_type, 0); }
};

It behaves like any class, its destructor runs on scope end.它的行为与任何 class 一样,其析构函数在 scope 结束时运行。

In C, using gcc, cleanup handlers require pthread_exit() , but your code does return .在 C 中,使用 gcc,清理处理程序需要pthread_exit() ,但您的代码确实return了。

  1. When a thread terminates by callingpthread_exit(3) , all clean-up handlers are executed as described in the preceding point.当线程通过调用pthread_exit(3)终止时,所有清理处理程序都将按照前一点所述执行。 (Clean-up handlers are not called if the thread terminates by performing a return from the thread start function.) (如果线程通过从线程开始 function 执行返回而终止,则不会调用清理处理程序。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM