1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Tests for fork in multi-threaded environment. 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2000 Free Software Foundation, Inc. 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU C Library is free software; you can redistribute it and/or 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU Library General Public License as 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU C Library is distributed in the hope that it will be useful, 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but WITHOUT ANY WARRANTY; without even the implied warranty of 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Library General Public License for more details. 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU Library General Public 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License along with the GNU C Library; see the file COPYING.LIB. If not, 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Boston, MA 02111-1307, USA. */ 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h> 21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if !defined(__APPLE__) 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# include <error.h> 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/wait.h> 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(__APPLE__) 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h> /* strerror */ 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void error (int status, int errnum, char* msg) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "%s%s%s\n", 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown msg, 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errnum ? ": " : "", 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errnum ? strerror(errnum) : ""); 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (errnum) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit(errnum); 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PREPARE_BIT = 1, 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PARENT_BIT = 2, 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CHILD_BIT = 4 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int var; 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownprepare (void) 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var |= PREPARE_BIT; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownparent (void) 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var |= PARENT_BIT; 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchild (void) 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown var |= CHILD_BIT; 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void *thread (void *arg); 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmain (void) 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t th; 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *res; 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_atfork (prepare, parent, child); 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pthread_create (&th, NULL, thread, NULL) != 0) 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error (EXIT_FAILURE, 0, "cannot create thread"); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join (th, &res); 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( ( int ) ( long int ) res != 0 ) 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error(EXIT_FAILURE, 0, "pthread_join res != 0" ); 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf ( "all ok\n" ); 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void * 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthread (void *arg) 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int status; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid_t pid; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid = fork (); 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pid == 0) 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We check whether the `prepare' and `child' function ran. */ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit (var != (PREPARE_BIT | CHILD_BIT)); 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (pid == (pid_t) -1) 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error (EXIT_FAILURE, errno, "cannot fork"); 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (waitpid (pid, &status, 0) != pid) 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error (EXIT_FAILURE, errno, "wrong child"); 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (WTERMSIG (status) != 0) 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error (EXIT_FAILURE, 0, "Child terminated incorrectly"); 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status = WEXITSTATUS (status); 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (status == 0) 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status = var != (PREPARE_BIT | PARENT_BIT); 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void *) (long int) status; 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 122