Blame stdlib/test-dlclose-exit-race.c

Packit Service 82fcde
/* Test for exit/dlclose race (Bug 22180).
Packit Service 82fcde
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* This file must be run from within a directory called "stdlib".  */
Packit Service 82fcde
Packit Service 82fcde
/* This test verifies that when dlopen in one thread races against exit
Packit Service 82fcde
   in another thread, we don't call registered destructor twice.
Packit Service 82fcde
Packit Service 82fcde
   Expected result:
Packit Service 82fcde
     second
Packit Service 82fcde
     first
Packit Service 82fcde
     ... clean termination
Packit Service 82fcde
*/
Packit Service 82fcde
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <semaphore.h>
Packit Service 82fcde
#include <support/check.h>
Packit Service 82fcde
#include <support/xdlfcn.h>
Packit Service 82fcde
#include <support/xthread.h>
Packit Service 82fcde
Packit Service 82fcde
/* Semaphore to ensure we have a happens-before between the first function
Packit Service 82fcde
   starting and exit being called.  */
Packit Service 82fcde
sem_t order1;
Packit Service 82fcde
Packit Service 82fcde
/* Semaphore to ensure we have a happens-before between the second function
Packit Service 82fcde
   starting and the first function returning.  */
Packit Service 82fcde
sem_t order2;
Packit Service 82fcde
Packit Service 82fcde
void *
Packit Service 82fcde
exit_thread (void *arg)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Wait for the dlclose to start...  */
Packit Service 82fcde
  sem_wait (&order1;;
Packit Service 82fcde
  /* Then try to run the exit sequence which should call all
Packit Service 82fcde
     __cxa_atexit registered functions and in parallel with
Packit Service 82fcde
     the executing dlclose().  */
Packit Service 82fcde
  exit (0);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
last (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Let dlclose thread proceed.  */
Packit Service 82fcde
  sem_post (&order2;;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
main (void)
Packit Service 82fcde
{
Packit Service 82fcde
  void *dso;
Packit Service 82fcde
  pthread_t thread;
Packit Service 82fcde
Packit Service 82fcde
  atexit (last);
Packit Service 82fcde
Packit Service 82fcde
  dso = xdlopen ("$ORIGIN/test-dlclose-exit-race-helper.so",
Packit Service 82fcde
		 RTLD_NOW|RTLD_GLOBAL);
Packit Service 82fcde
  thread = xpthread_create (NULL, exit_thread, NULL);
Packit Service 82fcde
Packit Service 82fcde
  xdlclose (dso);
Packit Service 82fcde
  xpthread_join (thread);
Packit Service 82fcde
Packit Service 82fcde
  FAIL_EXIT1 ("Did not terminate via exit(0) in exit_thread() as expected.");
Packit Service 82fcde
}