(root)/
glibc-2.38/
sysdeps/
pthread/
tst-atfork4.c
       1  /* pthread_atfork supports handlers that call pthread_atfork or dlclose.
       2     Copyright (C) 2022-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 <support/xdlfcn.h>
      20  #include <stdio.h>
      21  #include <support/xthread.h>
      22  #include <sys/types.h>
      23  #include <sys/wait.h>
      24  #include <support/xunistd.h>
      25  #include <support/check.h>
      26  #include <stdlib.h>
      27  
      28  static void *
      29  thread_func (void *x)
      30  {
      31    return NULL;
      32  }
      33  
      34  static unsigned int second_atfork_handler_runcount = 0;
      35  
      36  static void
      37  second_atfork_handler (void)
      38  {
      39    second_atfork_handler_runcount++;
      40  }
      41  
      42  static void *h = NULL;
      43  
      44  static unsigned int atfork_handler_runcount = 0;
      45  
      46  static void
      47  prepare (void)
      48  {
      49    /* These atfork handlers are registered while atfork handlers are being
      50       executed and thus will not be executed during the corresponding
      51       fork.  */
      52    TEST_VERIFY_EXIT (pthread_atfork (second_atfork_handler,
      53                                      second_atfork_handler,
      54                                      second_atfork_handler) == 0);
      55  
      56    /* This will de-register the atfork handlers registered by the dlopen'd
      57       library and so they will not be executed.  */
      58    if (h != NULL)
      59      {
      60        xdlclose (h);
      61        h = NULL;
      62      }
      63  
      64    atfork_handler_runcount++;
      65  }
      66  
      67  static void
      68  after (void)
      69  {
      70    atfork_handler_runcount++;
      71  }
      72  
      73  static int
      74  do_test (void)
      75  {
      76    /* Make sure __libc_single_threaded is 0.  */
      77    pthread_attr_t attr;
      78    xpthread_attr_init (&attr);
      79    xpthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
      80    xpthread_create (&attr, thread_func, NULL);
      81  
      82    void (*reg_atfork_handlers) (void);
      83  
      84    h = xdlopen ("tst-atfork4mod.so", RTLD_LAZY);
      85  
      86    reg_atfork_handlers = xdlsym (h, "reg_atfork_handlers");
      87  
      88    reg_atfork_handlers ();
      89  
      90    /* We register our atfork handlers *after* loading the module so that our
      91       prepare handler is called first at fork, where we then dlclose the
      92       module before its prepare handler has a chance to be called.  */
      93    TEST_VERIFY_EXIT (pthread_atfork (prepare, after, after) == 0);
      94  
      95    pid_t pid = xfork ();
      96  
      97    /* Both the parent and the child processes should observe this.  */
      98    TEST_VERIFY_EXIT (atfork_handler_runcount == 2);
      99    TEST_VERIFY_EXIT (second_atfork_handler_runcount == 0);
     100  
     101    if (pid > 0)
     102      {
     103        int childstat;
     104  
     105        xwaitpid (-1, &childstat, 0);
     106        TEST_VERIFY_EXIT (WIFEXITED (childstat)
     107                          && WEXITSTATUS (childstat) == 0);
     108  
     109        /* This time, the second set of atfork handlers should also be called
     110           since the handlers are already in place before fork is called.  */
     111  
     112        pid = xfork ();
     113  
     114        TEST_VERIFY_EXIT (atfork_handler_runcount == 4);
     115        TEST_VERIFY_EXIT (second_atfork_handler_runcount == 2);
     116  
     117        if (pid > 0)
     118          {
     119            xwaitpid (-1, &childstat, 0);
     120            TEST_VERIFY_EXIT (WIFEXITED (childstat)
     121                              && WEXITSTATUS (childstat) == 0);
     122          }
     123      }
     124  
     125    return 0;
     126  }
     127  
     128  #include <support/test-driver.c>