Home | History | Annotate | Download | only in tests
      1 /* Tests for fork in multi-threaded environment.
      2    Copyright (C) 2000 Free Software Foundation, Inc.
      3    Contributed by Ulrich Drepper <drepper (at) cygnus.com>, 2000.
      4 
      5    The GNU C Library is free software; you can redistribute it and/or
      6    modify it under the terms of the GNU Library General Public License as
      7    published by the Free Software Foundation; either version 2 of the
      8    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    Library General Public License for more details.
     14 
     15    You should have received a copy of the GNU Library General Public
     16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
     17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     18    Boston, MA 02111-1307, USA.  */
     19 
     20 #include <errno.h>
     21 #if !defined(__APPLE__) && !defined(__sun)
     22 # include <error.h>
     23 #endif
     24 #include <stdlib.h>
     25 #include <pthread.h>
     26 #include <unistd.h>
     27 #include <sys/wait.h>
     28 #include <stdio.h>
     29 
     30 #if defined(__APPLE__) || defined(__sun)
     31 #include <string.h>  /* strerror */
     32 static void error (int status, int errnum, char* msg)
     33 {
     34    fprintf(stderr, "%s%s%s\n",
     35            msg,
     36            errnum ? ": " : "",
     37            errnum ? strerror(errnum) : "");
     38    if (errnum)
     39       exit(errnum);
     40 }
     41 #endif
     42 
     43 enum
     44 {
     45   PREPARE_BIT = 1,
     46   PARENT_BIT = 2,
     47   CHILD_BIT = 4
     48 };
     49 
     50 static int var;
     51 
     52 static void
     53 prepare (void)
     54 {
     55   var |= PREPARE_BIT;
     56 }
     57 
     58 static void
     59 parent (void)
     60 {
     61   var |= PARENT_BIT;
     62 }
     63 
     64 static void
     65 child (void)
     66 {
     67   var |= CHILD_BIT;
     68 }
     69 
     70 
     71 static void *thread (void *arg);
     72 
     73 
     74 int
     75 main (void)
     76 {
     77   pthread_t th;
     78   void *res;
     79 
     80   pthread_atfork (prepare, parent, child);
     81 
     82   if (pthread_create (&th, NULL, thread, NULL) != 0)
     83     error (EXIT_FAILURE, 0, "cannot create thread");
     84 
     85   pthread_join (th, &res);
     86 
     87   if ( ( int ) ( long int ) res != 0 )
     88       error(EXIT_FAILURE, 0, "pthread_join res != 0" );
     89 
     90   printf ( "all ok\n" );
     91   return 0;
     92 }
     93 
     94 
     95 static void *
     96 thread (void *arg)
     97 {
     98   int status;
     99   pid_t pid;
    100 
    101   pid = fork ();
    102   if (pid == 0)
    103     {
    104       /* We check whether the `prepare' and `child' function ran.  */
    105       exit (var != (PREPARE_BIT | CHILD_BIT));
    106     }
    107   else if (pid == (pid_t) -1)
    108     error (EXIT_FAILURE, errno, "cannot fork");
    109 
    110   if (waitpid (pid, &status, 0) != pid)
    111     error (EXIT_FAILURE, errno, "wrong child");
    112 
    113   if (WTERMSIG (status) != 0)
    114     error (EXIT_FAILURE, 0, "Child terminated incorrectly");
    115   status = WEXITSTATUS (status);
    116 
    117   if (status == 0)
    118     status = var != (PREPARE_BIT | PARENT_BIT);
    119 
    120   return (void *) (long int) status;
    121 }
    122