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