mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
I tried using 'svn merge' to do the merge but it did a terrible job and there were bazillions of conflicts. So instead I just took the diff between the branch and trunk at r10155, applied the diff to the trunk, 'svn add'ed the added files (no files needed to be 'svn remove'd) and committed. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10156
122 lines
2.6 KiB
C
122 lines
2.6 KiB
C
/* Tests for fork in multi-threaded environment.
|
|
Copyright (C) 2000 Free Software Foundation, Inc.
|
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
#include <errno.h>
|
|
#if !defined(_AIX) && !defined(__APPLE__)
|
|
# include <error.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <stdio.h>
|
|
|
|
#if defined(_AIX) || defined(__APPLE__)
|
|
#include <string.h> /* strerror */
|
|
static void error (int status, int errnum, char* msg)
|
|
{
|
|
fprintf(stderr, "%s%s%s\n",
|
|
msg,
|
|
errnum ? ": " : "",
|
|
errnum ? strerror(errnum) : "");
|
|
if (errnum)
|
|
exit(errnum);
|
|
}
|
|
#endif
|
|
|
|
enum
|
|
{
|
|
PREPARE_BIT = 1,
|
|
PARENT_BIT = 2,
|
|
CHILD_BIT = 4
|
|
};
|
|
|
|
static int var;
|
|
|
|
static void
|
|
prepare (void)
|
|
{
|
|
var |= PREPARE_BIT;
|
|
}
|
|
|
|
static void
|
|
parent (void)
|
|
{
|
|
var |= PARENT_BIT;
|
|
}
|
|
|
|
static void
|
|
child (void)
|
|
{
|
|
var |= CHILD_BIT;
|
|
}
|
|
|
|
|
|
static void *thread (void *arg);
|
|
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
pthread_t th;
|
|
void *res;
|
|
|
|
pthread_atfork (prepare, parent, child);
|
|
|
|
if (pthread_create (&th, NULL, thread, NULL) != 0)
|
|
error (EXIT_FAILURE, 0, "cannot create thread");
|
|
|
|
pthread_join (th, &res);
|
|
|
|
if ( ( int ) ( long int ) res != 0 )
|
|
error(EXIT_FAILURE, 0, "pthread_join res != 0" );
|
|
|
|
printf ( "all ok\n" );
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void *
|
|
thread (void *arg)
|
|
{
|
|
int status;
|
|
pid_t pid;
|
|
|
|
pid = fork ();
|
|
if (pid == 0)
|
|
{
|
|
/* We check whether the `prepare' and `child' function ran. */
|
|
exit (var != (PREPARE_BIT | CHILD_BIT));
|
|
}
|
|
else if (pid == (pid_t) -1)
|
|
error (EXIT_FAILURE, errno, "cannot fork");
|
|
|
|
if (waitpid (pid, &status, 0) != pid)
|
|
error (EXIT_FAILURE, errno, "wrong child");
|
|
|
|
if (WTERMSIG (status) != 0)
|
|
error (EXIT_FAILURE, 0, "Child terminated incorrectly");
|
|
status = WEXITSTATUS (status);
|
|
|
|
if (status == 0)
|
|
status = var != (PREPARE_BIT | PARENT_BIT);
|
|
|
|
return (void *) (long int) status;
|
|
}
|