Search code examples
c++linuxpthreadsqnx

Use pthread_cancel in QNX system has a memory leak, but it does not exist on the Linux system


I have a code, main thread create 2 thread(thread_1 and thread_2), I use pthread_cancel to cancel thread_1 in thread_2, but the data that I create in thread_1 will not be destructored when I run it in QNX system, but there is no problem in Linux system.

It my test code, when I run it in QNX system,MyClass and MyClass2 object destructor not be called, so the 100M memory will leak; but run it in Linux system,it will call MyClass and MyClass2 object destructor. why is there such a difference???

#include <iostream>
#include <pthread.h>
#include <thread>

using namespace std;

pthread_t thread_id_1;
pthread_t thread_id_2;

class MyClass2
{
public:
    MyClass2() {
        cout << "Build MyClass2" << endl;
    }
    ~MyClass2() {
        cout << "Destory MyClass2" << endl;
    }
};

class MyClass
{
public:
    MyClass() {
        cout << "Build MyClass" << endl;
        p = (char *)malloc(1024 * 1024 *100);
    }
    ~MyClass() {
        cout << "Destory MyClass" << endl;
        free(p);
    }
    char *p;
};

void func(int i)
{
    MyClass2 c2;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    cout << "thread 1 func:" << i << endl;
}

static void *thread_1(void *arg)
{
    MyClass my_class;
    int type_value = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    cout << "thread_1 set cancle type+++++:" << type_value << endl;
    for (int i = 0; i < 10; i++) {
        func(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    return nullptr;
}

static void *thread_2(void *arg)
{
    for (int i = 0; i < 10; i++) {
        cout << "thread_2:" << i << endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    int ret = pthread_cancel(thread_id_1);
    cout << "otx_thread_2 cancel thread 1 ret:" << ret << endl;
    return nullptr;
}

int main(int argc, char *argv[])
{
    cout << "Main start" << endl;

    pthread_attr_t attr;
    pthread_attr_init( &attr );
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    cout << "Main set detch" << endl;
    if (pthread_create(&thread_id_1, &attr, thread_1, nullptr) != 0) {
        cout << "pthread_create() 1 error" << endl;
        return -1;
    }
    if (pthread_create(&thread_id_2, nullptr, thread_2, nullptr) != 0) {
        cout << "pthread_create() 2 error" << endl;
        return -1;
    }
    if (pthread_join(thread_id_2, NULL) != 0) {
        cout << "pthread_join() 1 error";
        return -1;
    }
    while (1) {
        cout << "Main Loop" << endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    return 0;
}

enter image description here enter image description here

I try it again and again, so I confirm that there is no problem with the code, But I don't understand why there is such a difference


Solution

  • pthread_cancel is outside the scope of the C++ specification. C++ does not specify its behavior, nor inherit it from C or POSIX.

    The difference is simply because QNX and Linux have implemented pthread_cancel differently in a C++ environment. There is literally nothing more to it than that.

    I imagine that the QNX implementation stops the thread in its tracks, whereas the Linux implementation probably induces an exception which unwinds the canceled thread's stack.