pthread cleanup functions

From: Paul Floyd <paulf2718_at_gmail.com>
Date: Fri, 01 Mar 2024 10:22:35 UTC
Hi

Can anyone explain what the pthread cleanup functions do?

I'm getting errors from Valgrind on arm64:

==8227== Invalid read of size 8
==8227==    at 0x48FFE78: __pthread_cleanup_pop_imp (in /lib/libthr.so.3)
==8227==  Address 0x1ffeffedf0 is on thread 2's stack
==8227==  328 bytes below stack pointer

I'm not doing a good job with the callstack, in gdb it's clearer and 
looks OK:

(gdb) bt
#0  __thr_cleanup_pop_imp (execute=execute@entry=1) at 
/usr/src/lib/libthr/thread/thr_clean.c:78
#1  0x0000000004901aa4 in _pthread_exit_mask (status=<optimized out>, 
mask=<optimized out>, mask@entry=0x1ffeffefa8)
     at /usr/src/lib/libthr/thread/thr_exit.c:260
#2  0x0000000004901944 in _Tthr_exit (status=0x1) at 
/usr/src/lib/libthr/thread/thr_exit.c:207
#3  0x0000000004901350 in thread_start (curthread=0x557c780) at 
/usr/src/lib/libthr/thread/thr_create.c:290
#4  0x0000000004900ec0 in _pthread_create (thread=0x1ffffff930, 
attr=<optimized out>, start_routine=<optimized out>, arg=<optimized out>)
     at /usr/src/lib/libthr/thread/thr_create.c:185
#5  0x0000000000210840 in main () at pthread.c:22


That's on line 78 below. curthread->cleanup is not NULL but it points to 
invalid memory.

71  void
72  __thr_cleanup_pop_imp(int execute)
73  {
74          struct pthread  *curthread = _get_curthread();
75          struct pthread_cleanup *old;
76
77          if ((old = curthread->cleanup) != NULL) {
78                  curthread->cleanup = old->prev;
79                  if (execute)
80                          old->routine(old->routine_arg);
81                  if (old->onheap)
82                          free(old); 

83          }
84  }

This is just running a trivial example

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

void* func(void* arg)
{
     int a;
     fprintf(stderr,  "in func arg passed is %p\n", arg);
     fprintf(stderr,  "in func arg my stack is around %p\n", &a);
     return NULL;
}

int main(void)
{
     int arg = 42;
     pthread_t tid;
     fprintf(stderr,  "arg passed is %p\n", &arg);
     pthread_create(&tid,
         NULL,
         func,
         &arg);

     pthread_join(tid, NULL);
}

A+
Paul