6

If I have an initialised pthread_barrier_t, when is it safe to destroy it? Is the following example safe?

pthread_barrier_t barrier;
...
int rc = pthread_barrier_wait(b);
if (rc != PTHREAD_BARRIER_SERIAL_THREAD && rc != 0){
  perror("pthread_barrier_wait");
  exit(1);
}

if (id == 0){
  if(pthread_barrier_destroy(&(threads[t_root].info.tmp_barrier))){
    perror("pthread_barrier_destroy");
    exit(1);
  }
}
fmark
  • 57,259
  • 27
  • 100
  • 107

2 Answers2

5

After pthread_barrier_wait() returns, all threads will have hit the barrier and are proceeding. Since only one thread is given the PTHREAD_BARRIER_SERIAL_THREAD return value, it's safe to use that to conditionally wrap the destruction code like so:

int rc = pthread_barrier_wait(&b)
if ( rc == PTHREAD_BARRIER_SERIAL_THREAD )
{
    pthread_barrier_destroy(&b);
}

Also, be aware that pthread_barrier_destroy() will return a result of EBUSY if the barrier was in use (i.e. another thread had called pthread_barrier_wait()).

Jim Dovey
  • 11,166
  • 2
  • 33
  • 40
  • 4
    The final sentence of your answer is false. Per POSIX, it is UB: "The results are undefined if pthread_barrier_destroy() is called when any thread is blocked on the barrier, or if this function is called with an uninitialized barrier." (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_destroy.html) – R.. GitHub STOP HELPING ICE Mar 23 '11 at 18:18
3

The accepted answer is incorrect. A return value of PTHREAD_BARRIER_SERIAL_THREAD does not mean it is safe to destroy the barrier.

You need additional synchronization before destroying the barrier.

The problem is that a destroy call can occur whilst other threads are in the process of leaving the barrier. These threads need to check the state of the barrier due to the fact that the futex system call can have "false wakeups". If the memory used by the barrier is freed out from underneath them, then undefined behaviour will occur.

Thus the destroying thread needs to wait until all other threads have finished exiting the barrier. In order for that to happen, extra synchronization is required. Source with alternative implementation using pthread_cond

In this issue, the user is doing the same logic as you have in your example code. https://groups.google.com/forum/#!topic/thread-sanitizer/81idLTirikQ

Community
  • 1
  • 1
dpsi
  • 31
  • 1
  • To recap, a return of PTHREAD_BARRIER_SERIAL_THREAD does not guarantee that all other threads have exited the barrier — you do not know that you are the last thread to leave. If any other threads are still 'inside' the barrier, it is unsafe to destroy it. – pilcrow Dec 20 '20 at 23:45