pth_atfork1.c revision 8f943afc22a6a683b78271836c8ddc462b4824a9
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 */
32static 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
43enum
44{
45  PREPARE_BIT = 1,
46  PARENT_BIT = 2,
47  CHILD_BIT = 4
48};
49
50static int var;
51
52static void
53prepare (void)
54{
55  var |= PREPARE_BIT;
56}
57
58static void
59parent (void)
60{
61  var |= PARENT_BIT;
62}
63
64static void
65child (void)
66{
67  var |= CHILD_BIT;
68}
69
70
71static void *thread (void *arg);
72
73
74int
75main (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
95static void *
96thread (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