Back to index

glibc  2.9
ex8.c
Go to the documentation of this file.
00001 /* Tests for fork in multi-threaded environment.
00002    Copyright (C) 2000 Free Software Foundation, Inc.
00003    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public License as
00007    published by the Free Software Foundation; either version 2.1 of the
00008    License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00017    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.  */
00019 
00020 #include <errno.h>
00021 #include <error.h>
00022 #include <stdlib.h>
00023 #include <pthread.h>
00024 #include <unistd.h>
00025 #include <sys/wait.h>
00026 
00027 enum
00028 {
00029   PREPARE_BIT = 1,
00030   PARENT_BIT = 2,
00031   CHILD_BIT = 4
00032 };
00033 
00034 static int var;
00035 
00036 static void
00037 prepare (void)
00038 {
00039   var |= PREPARE_BIT;
00040 }
00041 
00042 static void
00043 parent (void)
00044 {
00045   var |= PARENT_BIT;
00046 }
00047 
00048 static void
00049 child (void)
00050 {
00051   var |= CHILD_BIT;
00052 }
00053 
00054 
00055 static void *thread (void *arg);
00056 
00057 
00058 int
00059 main (void)
00060 {
00061   pthread_t th;
00062   void *res;
00063 
00064   pthread_atfork (prepare, parent, child);
00065 
00066   if (pthread_create (&th, NULL, thread, NULL) != 0)
00067     error (EXIT_FAILURE, 0, "cannot create thread");
00068 
00069   pthread_join (th, &res);
00070 
00071   return (int) (long int) res;
00072 }
00073 
00074 
00075 static void *
00076 thread (void *arg)
00077 {
00078   int status;
00079   pid_t pid;
00080 
00081   pid = fork ();
00082   if (pid == 0)
00083     {
00084       /* We check whether the `prepare' and `child' function ran.  */
00085       exit (var != (PREPARE_BIT | CHILD_BIT));
00086     }
00087   else if (pid == (pid_t) -1)
00088     error (EXIT_FAILURE, errno, "cannot fork");
00089 
00090   if (waitpid (pid, &status, 0) != pid)
00091     error (EXIT_FAILURE, errno, "wrong child");
00092 
00093   if (WTERMSIG (status) != 0)
00094     error (EXIT_FAILURE, 0, "Child terminated incorrectly");
00095   status = WEXITSTATUS (status);
00096 
00097   if (status == 0)
00098     status = var != (PREPARE_BIT | PARENT_BIT);
00099 
00100   return (void *) (long int) status;
00101 }