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