(root)/
glibc-2.38/
stdlib/
test-dlclose-exit-race-helper.c
       1  /* Helper for exit/dlclose race test (Bug 22180).
       2     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <stdio.h>
      20  #include <stdbool.h>
      21  #include <stdlib.h>
      22  #include <semaphore.h>
      23  #include <unistd.h>
      24  #include <support/check.h>
      25  #include <support/xthread.h>
      26  
      27  /* Semaphore defined in executable to ensure we have a happens-before
      28     between the first function starting and exit being called.  */
      29  extern sem_t order1;
      30  
      31  /* Semaphore defined in executable to ensure we have a happens-before
      32     between the second function starting and the first function returning.  */
      33  extern sem_t order2;
      34  
      35  /* glibc function for registering DSO-specific exit functions.  */
      36  extern int __cxa_atexit (void (*func) (void *), void *arg, void *dso_handle);
      37  
      38  /* Hidden compiler handle to this shared object.  */
      39  extern void *__dso_handle __attribute__ ((__weak__));
      40  
      41  static void
      42  first (void *start)
      43  {
      44    /* Let the exiting thread run.  */
      45    sem_post (&order1);
      46  
      47    /* Wait for exiting thread to finish.  */
      48    sem_wait (&order2);
      49  
      50    printf ("first\n");
      51  }
      52  
      53  static void
      54  second (void *start)
      55  {
      56    /* We may be called from different threads.
      57       This lock protects called.  */
      58    static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
      59    static bool called = false;
      60  
      61    xpthread_mutex_lock (&mtx);
      62    if (called)
      63      FAIL_EXIT1 ("second called twice!");
      64  
      65    called = true;
      66    xpthread_mutex_unlock (&mtx);
      67  
      68    printf ("second\n");
      69  }
      70  
      71  
      72  __attribute__ ((constructor)) static void
      73  constructor (void)
      74  {
      75    sem_init (&order1, 0, 0);
      76    sem_init (&order2, 0, 0);
      77    __cxa_atexit (second, NULL, __dso_handle);
      78    __cxa_atexit (first, NULL, __dso_handle);
      79  }