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__)
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__)
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