Back to index

glibc  2.9
tst-vfork2.c
Go to the documentation of this file.
00001 /* Test for vfork functions.
00002    Copyright (C) 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <signal.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <time.h>
00027 #include <unistd.h>
00028 #include <sys/time.h>
00029 #include <sys/types.h>
00030 #include <sys/wait.h>
00031 
00032 int raise_fail;
00033 
00034 static void
00035 alrm (int sig)
00036 {
00037   if (raise (SIGUSR1) < 0)
00038     raise_fail = 1;
00039 }
00040 
00041 /* This test relies on non-POSIX functionality since the child
00042    processes call write, nanosleep and getpid.  */
00043 static int
00044 do_test (void)
00045 {
00046   int result = 0;
00047   int fd[2];
00048 
00049   signal (SIGUSR1, SIG_IGN);
00050 
00051   struct sigaction sa;
00052   sa.sa_handler = alrm;
00053   sigemptyset (&sa.sa_mask);
00054   sa.sa_flags = 0;
00055   if (sigaction (SIGALRM, &sa, NULL) < 0)
00056     {
00057       puts ("couldn't set up SIGALRM handler");
00058       return 1;
00059     }
00060 
00061   if (pipe (fd) == -1)
00062     {
00063       puts ("pipe failed");
00064       return 1;
00065     }
00066 
00067   struct itimerval it;
00068   it.it_value.tv_sec = 0;
00069   it.it_value.tv_usec = 200 * 1000;
00070   it.it_interval = it.it_value;
00071   if (setitimer (ITIMER_REAL, &it, NULL) < 0)
00072     {
00073       puts ("couldn't set up timer");
00074       return 1;
00075     }
00076 
00077   /* First vfork() without previous getpid().  */
00078   pid_t p1;
00079   if ((p1 = vfork ()) == 0)
00080     {
00081       pid_t p = getpid ();
00082 
00083       struct timespec ts;
00084       ts.tv_sec = 1;
00085       ts.tv_nsec = 0;
00086       TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
00087       _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
00088     }
00089   else if (p1 == -1)
00090     {
00091       puts ("1st vfork failed");
00092       result = 1;
00093     }
00094 
00095   memset (&it, 0, sizeof (it));
00096   setitimer (ITIMER_REAL, &it, NULL);
00097 
00098   pid_t p2 = 0;
00099   if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
00100     {
00101       puts ("1st read failed");
00102       result = 1;
00103     }
00104   int r;
00105   if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
00106     {
00107       puts ("1st waitpid failed");
00108       result = 1;
00109     }
00110   else if (r != 0)
00111     {
00112       puts ("write in 1st child failed");
00113       result = 1;
00114     }
00115 
00116   /* Main process' ID.  */
00117   pid_t p0 = getpid ();
00118 
00119   /* vfork() again, but after a getpid() in the main process.  */
00120   pid_t p3;
00121   if ((p3 = vfork ()) == 0)
00122     {
00123       pid_t p = getpid ();
00124       _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
00125     }
00126   else if (p1 == -1)
00127     {
00128       puts ("2nd vfork failed");
00129       result = 1;
00130     }
00131 
00132   pid_t p4;
00133   if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
00134     {
00135       puts ("2nd read failed");
00136       result = 1;
00137     }
00138   if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
00139     {
00140       puts ("2nd waitpid failed");
00141       result = 1;
00142     }
00143   else if (r != 0)
00144     {
00145       puts ("write in 2nd child failed");
00146       result = 1;
00147     }
00148 
00149   /* And getpid in the main process again.  */
00150   pid_t p5 = getpid ();
00151 
00152   /* Analysis of the results.  */
00153   if (p0 != p5)
00154     {
00155       printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
00156       result = 1;
00157     }
00158 
00159   if (p0 == p1)
00160     {
00161       printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
00162       result = 1;
00163     }
00164 
00165   if (p1 != p2)
00166     {
00167       printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
00168       result = 1;
00169     }
00170 
00171   if (p0 == p3)
00172     {
00173       printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
00174       result = 1;
00175     }
00176 
00177   if (p3 != p4)
00178     {
00179       printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
00180       result = 1;
00181     }
00182 
00183   close (fd[0]);
00184   close (fd[1]);
00185 
00186   if (raise_fail)
00187     {
00188       puts ("raise failed");
00189       result = 1;
00190     }
00191 
00192   if (result == 0)
00193     puts ("All OK");
00194 
00195   return result;
00196 }
00197 
00198 #define TEST_FUNCTION do_test ()
00199 #include "../test-skeleton.c"