byannoni / qthreads

A POSIX thread wrapper using a pool and queues of functions for C and (soon) C++
Apache License 2.0
1 stars 1 forks source link

Investigate clobber warning/error #67

Closed byannoni closed 7 years ago

byannoni commented 7 years ago

In byannoni/qthreads#66 a new error suppression was introduced (cbf8203) due to a new message from GCC (and not clang) about local variable clobbering related to setjmp. This should be investigated.

function_queue.c: In function ‘fqpop’:
function_queue.c:167:15: warning: variable ‘ret’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
  enum qterror ret = QTSUCCESS;
               ^~~
function_queue.c: In function ‘fqpeek’:
function_queue.c:232:15: warning: variable ‘ret’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
  enum qterror ret = QTSUCCESS;
               ^~~
byannoni commented 7 years ago

It turns out GCC was correct that the variable could be clobbered, but the warning is irrelevant because the value can no longer be accessed at that point anyway.

The issue is that pthread_cleanup_push() is a macro which uses __sigsetjmp(). However, if __sigsetjmp() returns the second time (if the thread must clean up), it calls __pthread_unwind_next() which has the attribute __noreturn__. As indicated by the comment below, code beyond that point would not be reached. Thus, this warning is not a concern. The warning could be suppressed by changing ret to be volatile. (See #76).

Relevant segments from pthread.h:

# define pthread_cleanup_push(routine, arg) \
    /* ... */                                                 \
    int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *)     \
                    __cancel_buf.__cancel_jmp_buf, 0);    \
    if (__glibc_unlikely (__not_first_call))                      \
      {                                       \
    __cancel_routine (__cancel_arg);                      \
    __pthread_unwind_next (&__cancel_buf);                    \
    /* NOTREACHED */                              \
      }                                       \
    /* ... */
extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
     __cleanup_fct_attribute __attribute__ ((__noreturn__))
    /* ... */