1 /* Basic tests for _Fork.
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <array_length.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <pthread.h>
23 #include <stdbool.h>
24 #include <support/check.h>
25 #include <support/xsignal.h>
26 #include <support/temp_file.h>
27 #include <support/xunistd.h>
28 #include <support/xthread.h>
29 
30 /* For single-thread, _Fork behaves like fork.  */
31 static int
singlethread_test(void)32 singlethread_test (void)
33 {
34   const char testdata1[] = "abcdefghijklmnopqrtuvwxz";
35   enum { testdatalen1 = array_length (testdata1) };
36   const char testdata2[] = "01234567890";
37   enum { testdatalen2 = array_length (testdata2) };
38 
39   pid_t ppid = getpid ();
40 
41   int tempfd = create_temp_file ("tst-_Fork", NULL);
42 
43   /* Check if the opened file is shared between process by read and write
44      some data on parent and child processes.  */
45   xwrite (tempfd, testdata1, testdatalen1);
46   off_t off = xlseek (tempfd, 0, SEEK_CUR);
47   TEST_COMPARE (off, testdatalen1);
48 
49   pid_t pid = _Fork ();
50   TEST_VERIFY_EXIT (pid != -1);
51   if (pid == 0)
52     {
53       TEST_VERIFY_EXIT (getpid () != ppid);
54       TEST_COMPARE (getppid(), ppid);
55 
56       TEST_COMPARE (xlseek (tempfd, 0, SEEK_CUR), testdatalen1);
57 
58       xlseek (tempfd, 0, SEEK_SET);
59       char buf[testdatalen1];
60       TEST_COMPARE (read (tempfd, buf, sizeof (buf)), testdatalen1);
61       TEST_COMPARE_BLOB (buf, testdatalen1, testdata1, testdatalen1);
62 
63       xlseek (tempfd, 0, SEEK_SET);
64       xwrite (tempfd, testdata2, testdatalen2);
65 
66       xclose (tempfd);
67 
68       _exit (EXIT_SUCCESS);
69     }
70 
71   int status;
72   xwaitpid (pid, &status, 0);
73   TEST_VERIFY (WIFEXITED (status));
74   TEST_COMPARE (WEXITSTATUS (status), EXIT_SUCCESS);
75 
76   TEST_COMPARE (xlseek (tempfd, 0, SEEK_CUR), testdatalen2);
77 
78   xlseek (tempfd, 0, SEEK_SET);
79   char buf[testdatalen2];
80   TEST_COMPARE (read (tempfd, buf, sizeof (buf)), testdatalen2);
81 
82   TEST_COMPARE_BLOB (buf, testdatalen2, testdata2, testdatalen2);
83 
84   return 0;
85 }
86 
87 
88 #define SIG_PID_EXIT_CODE 20
89 
90 static bool atfork_prepare_var;
91 static bool atfork_parent_var;
92 static bool atfork_child_var;
93 
94 static void
atfork_prepare(void)95 atfork_prepare (void)
96 {
97   atfork_prepare_var = true;
98 }
99 
100 static void
atfork_parent(void)101 atfork_parent (void)
102 {
103   atfork_parent_var = true;
104 }
105 
106 static void
atfork_child(void)107 atfork_child (void)
108 {
109   atfork_child_var = true;
110 }
111 
112 /* Different than fork, _Fork does not execute any pthread_atfork
113    handlers.  */
114 static int
singlethread_atfork_test(void)115 singlethread_atfork_test (void)
116 {
117   pthread_atfork (atfork_prepare, atfork_parent, atfork_child);
118   singlethread_test ();
119   TEST_VERIFY (!atfork_prepare_var);
120   TEST_VERIFY (!atfork_parent_var);
121   TEST_VERIFY (!atfork_child_var);
122 
123   return 0;
124 }
125 
126 static void *
mt_atfork_test(void * args)127 mt_atfork_test (void *args)
128 {
129   singlethread_atfork_test ();
130 
131   return NULL;
132 }
133 
134 static int
multithread_atfork_test(void)135 multithread_atfork_test (void)
136 {
137   pthread_t thr = xpthread_create (NULL, mt_atfork_test, NULL);
138   xpthread_join (thr);
139 
140   return 0;
141 }
142 
143 
144 static int
do_test(void)145 do_test (void)
146 {
147   singlethread_atfork_test ();
148   multithread_atfork_test ();
149 
150   return 0;
151 }
152 
153 #include <support/test-driver.c>
154