1 /* Tests for fork in multi-threaded environment.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Contributed by Ulrich Drepper <drepper@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) && !defined(__DragonFly__)
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) || defined(__DragonFly__)
31 #include <string.h>  /* strerror */
error(int status,int errnum,char * msg)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
prepare(void)53 prepare (void)
54 {
55   var |= PREPARE_BIT;
56 }
57 
58 static void
parent(void)59 parent (void)
60 {
61   var |= PARENT_BIT;
62 }
63 
64 static void
child(void)65 child (void)
66 {
67   var |= CHILD_BIT;
68 }
69 
70 
71 static void *thread (void *arg);
72 
73 
74 int
main(void)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 *
thread(void * arg)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