1

I have a program which should start a thread. To avoid to exit the software the thread runs in an endless loop and I join the thread. This thread is never supposed to return a value. So now I have the problem that after I call pthread_cancel valgrind detects a memory leak. How can I avoid such memory leak?

Valgrind output:

==5673== 136 bytes in 1 blocks are possibly lost in loss record 4 of 8
==5673==    at 0x4026A68: calloc (vg_replace_malloc.c:566)
==5673==    by 0x40111FB: _dl_allocate_tls (dl-tls.c:300)
==5673==    by 0x404E5A0: pthread_create@@GLIBC_2.1 (allocatestack.c:580)
==5673==    by 0x804C44E: start (mythread.c:25)
==5673==    by 0x804D128: main (main.c:10)

code:

int main(){
    signal(SIGINT,cleanup);
    signal(SIGQUIT,cleanup);
    signal(SIGSEGV,cleanup);
    start();
    return 0;
}

int start()
{
    pthread_create(&thread_id[0],NULL,&threadhandler,NULL);
    pthread_join(thread_id[0],NULL);
    return err;
}

void cleanup(){
   pthread_cancel(thread_id[0]);
   exit(0);
}

void cleanup_tcp(void *p){
}


void* threadhandler(void *arg)
{
    (void) arg;
    int status = 0;
    while(TRUE){
        pthread_cleanup_push(cleanup_tcp,NULL);
        pthread_testcancel();
        fprintf(stderr,"Run\n");
        pthread_cleanup_pop(0);
    }
    return NULL;
}
mch
  • 9,424
  • 2
  • 28
  • 42
Irgendw Pointer
  • 1,770
  • 3
  • 30
  • 67
  • 1
    Detaching the thread (by calling `pthread_detach()`) prior to cancelling it might help (a bit). – alk Aug 02 '14 at 10:42

1 Answers1

1

You have correctly identified a drawback of using pthread_cancel(): any resource not released/freed by the thread cleanup routine will subsequently leak. In your case, it appears that the thread library, itself, might have allocated some memory that isn't being freed.

A better approach, IMO, would be to create a mechanism for notifying the threadhandler thread that it should terminate. For example

static volatile sig_atomic_t done = 0;
...
void cleanup()
{
    done = 1;
}

void* threadhandler(void* arg)
{
    while (!done)
        fprintf(stderr, "Run\n");
    return NULL;
}
Steve Emmerson
  • 7,702
  • 5
  • 33
  • 59
  • The `volatile` is superfluous and harmful. Using an atomic variable suffices. – cmaster - reinstate monica Jul 25 '14 at 16:23
  • @cmaster I disagree. The X/Open specification explicitly references the `volatile` qualifier: "If the signal occurs other than as the result of calling abort(), raise(), [CX] [Option Start] kill(), pthread_kill(), or sigqueue(), [Option End] the behavior is undefined if the signal handler refers to any object with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t, ...". Also, "The functionality described on this reference page is aligned with the ISO C standard". – Steve Emmerson Jul 25 '14 at 20:37
  • Ok, probably I don't know enough about X/Open, I judged by the terms of the C standard, assuming that `sig_atomic_t` is a type equivalent to what the C standard defines as being atomic. If that were the case, then the `volatile` is useless. But now it appears to me, that the X/Open specification was written before the C standard defined atomic types, so now I guess the `volatile` is indeed needed in conjunction with `sig_atomic_t`. Nevertheless, I would recommend using the atomic types of the current C standard instead. – cmaster - reinstate monica Jul 25 '14 at 20:53
  • @cmaster Be advised that not all platforms have a C11-conforming native compiler. – Steve Emmerson Jul 28 '14 at 15:06