Search code examples
cmultithreadingpthreads

pthread clean up int/array/struct type variables using pthread_cleanup_push


This may be a dumb question, but I am not familiar with multi-threaded programming and have googled a lot but could not find useful info. Let's say if I have a start function for a thread, which creates local variables of int/array/struct type, then I need to pthread_cancel this thread from another thread and clean up it like below (I know it may look problematic). How do I clean up those variables of int/array/struct type to avoid a memory leak?

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

pthread_t handler;

static void cleanup_int(void* arg){ /* clean up int */ }
static void cleanup_array(void* arg){ /* clean up array */ }
static void cleanup_srtuct(void* arg){ /* clean up struct */ }

static void* thread_func(void* p) {
    handler = pthread_self();
    int num = 0;  // variable of int type
    unsigned char array[8] = {0};  // variable of array type
    struct struct_var;  // variable of user defined struct type

    pthread_cleanup_push(cleanup_int, &num);
    pthread_cleanup_push(cleanup_array, array);
    pthread_cleanup_push(cleanup_struct, &struct_var);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    while (1) {
        printf("thread: %d\n", num);
        sleep(1);
    }
}
void main(void) {
    int count;
    pthread_t t;
   
    pthread_create(&t, NULL, thread_func, NULL);
    
    for(count = 0; count < 10; count++){
        printf("count = %d\n", count);
        if(count == 5){
            printf("terminate thread\n");
            pthread_cancel(handler);
        }
        sleep(1);
    }
}

I wonder how to clean up those variables which don't have explicit cleanup routine.

I have googled a lot and tried some simple programs, but still have no idea about how to handle these variables and/or other user-defined data structures.


Solution

  • how do I clean up those variables of int/array/struct type with memory leak?

    In the event that you ignore my advice in comments to avoid pthread_cancel(), this is a pretty good rule of thumb: at any given point in the program where you want robustness against ill effects from thread cancellation, the cleanup tasks that need to be provided by in-scope cleanup callbacks are exactly those that would be needed to allow a safe pthread_exit() call at the same point.

    In particular, you do not need to recover the storage of or twiddle the values of objects with automatic or thread storage duration, such as ordinary local variables, including structures, arrays, and their members / elements. If you have such objects that contain pointers to dynamically allocated objects, however, then you might need to deallocate the pointed-to objects. Depending on what your program does, you might need to clean up the values of dynamically or or statically allocated objects, especially including things like releasing mutexes and otherwise manipulating synchronization objects.

    With that in mind, I see no reason to think that you need cleanup handlers for any of the objects in the example code.

    Note also: it makes no sense to register a cleanup handler only to pop it immediately after. The handler should be pushed immediately after the statement that creates a need for it (or before, even, if that can be made to work), and it should be popped only after the cleanup is no longer needed. Very often, pthread_cleanup_pop() should be called with a non-zero argument, so that the cleanup is made unnecessary by running it.