1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. 3f08c3bdfSopenharmony_ci * Copyright (c) 2012 Wanlong Gao <gaowanlong@cn.fujitsu.com> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 6f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 7f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 10f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along 14f08c3bdfSopenharmony_ci * with this program; if not, write the Free Software Foundation, Inc., 15f08c3bdfSopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci */ 18f08c3bdfSopenharmony_ci/* 19f08c3bdfSopenharmony_ci * TEST1 20f08c3bdfSopenharmony_ci * ----- 21f08c3bdfSopenharmony_ci * Call clone() with all resources shared. 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * CHILD: 24f08c3bdfSopenharmony_ci * modify the shared resources 25f08c3bdfSopenharmony_ci * return 1 on success 26f08c3bdfSopenharmony_ci * PARENT: 27f08c3bdfSopenharmony_ci * wait for child to finish 28f08c3bdfSopenharmony_ci * verify that the shared resourses are modified 29f08c3bdfSopenharmony_ci * return 1 on success 30f08c3bdfSopenharmony_ci * If parent & child returns successfully 31f08c3bdfSopenharmony_ci * test passed 32f08c3bdfSopenharmony_ci * else 33f08c3bdfSopenharmony_ci * test failed 34f08c3bdfSopenharmony_ci * 35f08c3bdfSopenharmony_ci * TEST2 36f08c3bdfSopenharmony_ci * ----- 37f08c3bdfSopenharmony_ci * Call clone() with no resources shared. 38f08c3bdfSopenharmony_ci * 39f08c3bdfSopenharmony_ci * CHILD: 40f08c3bdfSopenharmony_ci * modify the resources in child's address space 41f08c3bdfSopenharmony_ci * return 1 on success 42f08c3bdfSopenharmony_ci * PARENT: 43f08c3bdfSopenharmony_ci * wait for child to finish 44f08c3bdfSopenharmony_ci * verify that the parent's resourses are not modified 45f08c3bdfSopenharmony_ci * return 1 on success 46f08c3bdfSopenharmony_ci * If parent & child returns successfully 47f08c3bdfSopenharmony_ci * test passed 48f08c3bdfSopenharmony_ci * else 49f08c3bdfSopenharmony_ci * test failed 50f08c3bdfSopenharmony_ci */ 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci#if defined UCLINUX && !__THROW 53f08c3bdfSopenharmony_ci/* workaround for libc bug */ 54f08c3bdfSopenharmony_ci#define __THROW 55f08c3bdfSopenharmony_ci#endif 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci#define _GNU_SOURCE 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci#include <errno.h> 60f08c3bdfSopenharmony_ci#include <fcntl.h> 61f08c3bdfSopenharmony_ci#include <sys/wait.h> 62f08c3bdfSopenharmony_ci#include <sys/types.h> 63f08c3bdfSopenharmony_ci#include <sys/syscall.h> 64f08c3bdfSopenharmony_ci#include <sched.h> 65f08c3bdfSopenharmony_ci#include "test.h" 66f08c3bdfSopenharmony_ci#include "safe_macros.h" 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci#define FLAG_ALL (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD) 69f08c3bdfSopenharmony_ci#define FLAG_NONE SIGCHLD 70f08c3bdfSopenharmony_ci#define PARENT_VALUE 1 71f08c3bdfSopenharmony_ci#define CHILD_VALUE 2 72f08c3bdfSopenharmony_ci#define TRUE 1 73f08c3bdfSopenharmony_ci#define FALSE 0 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#include "clone_platform.h" 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic void setup(void); 78f08c3bdfSopenharmony_cistatic int test_setup(void); 79f08c3bdfSopenharmony_cistatic void cleanup(void); 80f08c3bdfSopenharmony_cistatic void test_cleanup(void); 81f08c3bdfSopenharmony_cistatic int child_fn(); 82f08c3bdfSopenharmony_cistatic int parent_test1(void); 83f08c3bdfSopenharmony_cistatic int parent_test2(void); 84f08c3bdfSopenharmony_cistatic int test_VM(void); 85f08c3bdfSopenharmony_cistatic int test_FS(void); 86f08c3bdfSopenharmony_cistatic int test_FILES(void); 87f08c3bdfSopenharmony_cistatic int test_SIG(void); 88f08c3bdfSopenharmony_cistatic int modified_VM(void); 89f08c3bdfSopenharmony_cistatic int modified_FS(void); 90f08c3bdfSopenharmony_cistatic int modified_FILES(void); 91f08c3bdfSopenharmony_cistatic int modified_SIG(void); 92f08c3bdfSopenharmony_cistatic void sig_child_defined_handler(int); 93f08c3bdfSopenharmony_cistatic void sig_default_handler(); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic int fd_parent; 96f08c3bdfSopenharmony_cistatic char file_name[25]; 97f08c3bdfSopenharmony_cistatic int parent_variable; 98f08c3bdfSopenharmony_cistatic char cwd_parent[FILENAME_MAX]; 99f08c3bdfSopenharmony_cistatic int parent_got_signal, child_pid; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_cichar *TCID = "clone02"; 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_cistruct test_case_t { 104f08c3bdfSopenharmony_ci int flags; 105f08c3bdfSopenharmony_ci int (*parent_fn) (); 106f08c3bdfSopenharmony_ci} test_cases[] = { 107f08c3bdfSopenharmony_ci { 108f08c3bdfSopenharmony_ci FLAG_ALL, parent_test1}, { 109f08c3bdfSopenharmony_ci FLAG_NONE, parent_test2} 110f08c3bdfSopenharmony_ci}; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ciint TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ciint main(int ac, char **av) 115f08c3bdfSopenharmony_ci{ 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci int lc; 118f08c3bdfSopenharmony_ci void *child_stack; 119f08c3bdfSopenharmony_ci int status, i; 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci setup(); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci child_stack = malloc(CHILD_STACK_SIZE); 126f08c3bdfSopenharmony_ci if (child_stack == NULL) 127f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 130f08c3bdfSopenharmony_ci tst_count = 0; 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci for (i = 0; i < TST_TOTAL; ++i) { 133f08c3bdfSopenharmony_ci if (test_setup() != 0) { 134f08c3bdfSopenharmony_ci tst_resm(TWARN, "test_setup() failed, skipping this test case"); 135f08c3bdfSopenharmony_ci continue; 136f08c3bdfSopenharmony_ci } 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci /* Test the system call */ 139f08c3bdfSopenharmony_ci TEST(ltp_clone(test_cases[i].flags, child_fn, NULL, 140f08c3bdfSopenharmony_ci CHILD_STACK_SIZE, child_stack)); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci /* check return code */ 143f08c3bdfSopenharmony_ci if (TEST_RETURN == -1) { 144f08c3bdfSopenharmony_ci tst_resm(TFAIL | TTERRNO, "clone() failed"); 145f08c3bdfSopenharmony_ci /* Cleanup & continue with next test case */ 146f08c3bdfSopenharmony_ci test_cleanup(); 147f08c3bdfSopenharmony_ci continue; 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci /* Wait for child to finish */ 151f08c3bdfSopenharmony_ci if ((wait(&status)) == -1) { 152f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, 153f08c3bdfSopenharmony_ci "wait failed; skipping testcase"); 154f08c3bdfSopenharmony_ci /* Cleanup & continue with next test case */ 155f08c3bdfSopenharmony_ci test_cleanup(); 156f08c3bdfSopenharmony_ci continue; 157f08c3bdfSopenharmony_ci } 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci if (WTERMSIG(status)) 160f08c3bdfSopenharmony_ci tst_resm(TWARN, "child exitied with signal %d", 161f08c3bdfSopenharmony_ci WTERMSIG(status)); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci /* 164f08c3bdfSopenharmony_ci * Check the return value from child function and 165f08c3bdfSopenharmony_ci * parent function. If both functions returned 166f08c3bdfSopenharmony_ci * successfully, test passed, else failed 167f08c3bdfSopenharmony_ci */ 168f08c3bdfSopenharmony_ci if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && 169f08c3bdfSopenharmony_ci test_cases[i].parent_fn()) 170f08c3bdfSopenharmony_ci tst_resm(TPASS, "Test Passed"); 171f08c3bdfSopenharmony_ci else 172f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Test Failed"); 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci /* Do test specific cleanup */ 175f08c3bdfSopenharmony_ci test_cleanup(); 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci } 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci free(child_stack); 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci cleanup(); 182f08c3bdfSopenharmony_ci tst_exit(); 183f08c3bdfSopenharmony_ci} 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_cistatic void setup(void) 186f08c3bdfSopenharmony_ci{ 187f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 188f08c3bdfSopenharmony_ci TEST_PAUSE; 189f08c3bdfSopenharmony_ci tst_tmpdir(); 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci /* Get unique file name for each child process */ 192f08c3bdfSopenharmony_ci if ((sprintf(file_name, "parent_file_%ld", syscall(__NR_gettid))) <= 0) 193f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "sprintf() failed"); 194f08c3bdfSopenharmony_ci} 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_cistatic void cleanup(void) 197f08c3bdfSopenharmony_ci{ 198f08c3bdfSopenharmony_ci if (unlink(file_name) == -1) 199f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "unlink(%s) failed", file_name); 200f08c3bdfSopenharmony_ci tst_rmdir(); 201f08c3bdfSopenharmony_ci} 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_cistatic int test_setup(void) 204f08c3bdfSopenharmony_ci{ 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci struct sigaction def_act; 207f08c3bdfSopenharmony_ci 208f08c3bdfSopenharmony_ci /* Save current working directory of parent */ 209f08c3bdfSopenharmony_ci if (getcwd(cwd_parent, sizeof(cwd_parent)) == NULL) { 210f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "getcwd() failed in test_setup()"); 211f08c3bdfSopenharmony_ci return -1; 212f08c3bdfSopenharmony_ci } 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci /* 215f08c3bdfSopenharmony_ci * Set value for parent_variable in parent, which will be 216f08c3bdfSopenharmony_ci * changed by child in test_VM(), for testing CLONE_VM flag 217f08c3bdfSopenharmony_ci */ 218f08c3bdfSopenharmony_ci parent_variable = PARENT_VALUE; 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci /* 221f08c3bdfSopenharmony_ci * Open file from parent, which will be closed by 222f08c3bdfSopenharmony_ci * child in test_FILES(), used for testing CLONE_FILES flag 223f08c3bdfSopenharmony_ci */ 224f08c3bdfSopenharmony_ci fd_parent = open(file_name, O_CREAT | O_RDWR, 0777); 225f08c3bdfSopenharmony_ci if (fd_parent == -1) { 226f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "open() failed in test_setup()"); 227f08c3bdfSopenharmony_ci return -1; 228f08c3bdfSopenharmony_ci } 229f08c3bdfSopenharmony_ci 230f08c3bdfSopenharmony_ci /* 231f08c3bdfSopenharmony_ci * set parent_got_signal to FALSE, used for testing 232f08c3bdfSopenharmony_ci * CLONE_SIGHAND flag 233f08c3bdfSopenharmony_ci */ 234f08c3bdfSopenharmony_ci parent_got_signal = FALSE; 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci /* Setup signal handler for SIGUSR2 */ 237f08c3bdfSopenharmony_ci def_act.sa_handler = sig_default_handler; 238f08c3bdfSopenharmony_ci def_act.sa_flags = SA_RESTART; 239f08c3bdfSopenharmony_ci sigemptyset(&def_act.sa_mask); 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci if (sigaction(SIGUSR2, &def_act, NULL) == -1) { 242f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "sigaction() failed in test_setup()"); 243f08c3bdfSopenharmony_ci return -1; 244f08c3bdfSopenharmony_ci } 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci return 0; 247f08c3bdfSopenharmony_ci} 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_cistatic void test_cleanup(void) 250f08c3bdfSopenharmony_ci{ 251f08c3bdfSopenharmony_ci 252f08c3bdfSopenharmony_ci /* Restore parent's working directory */ 253f08c3bdfSopenharmony_ci SAFE_CHDIR(cleanup, cwd_parent); 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci} 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_cistatic int child_fn(void) 258f08c3bdfSopenharmony_ci{ 259f08c3bdfSopenharmony_ci 260f08c3bdfSopenharmony_ci /* save child pid */ 261f08c3bdfSopenharmony_ci child_pid = syscall(__NR_gettid); 262f08c3bdfSopenharmony_ci 263f08c3bdfSopenharmony_ci if (test_VM() == 0 && test_FILES() == 0 && test_FS() == 0 && 264f08c3bdfSopenharmony_ci test_SIG() == 0) 265f08c3bdfSopenharmony_ci _exit(0); 266f08c3bdfSopenharmony_ci _exit(1); 267f08c3bdfSopenharmony_ci} 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_cistatic int parent_test1(void) 270f08c3bdfSopenharmony_ci{ 271f08c3bdfSopenharmony_ci 272f08c3bdfSopenharmony_ci /* 273f08c3bdfSopenharmony_ci * For first test case (with all flags set), all resources are 274f08c3bdfSopenharmony_ci * shared between parent and child. So whatever changes made by 275f08c3bdfSopenharmony_ci * child should get reflected in parent also. modified_*() 276f08c3bdfSopenharmony_ci * functions check this. All of them should return 1 for 277f08c3bdfSopenharmony_ci * parent_test1() to return 1 278f08c3bdfSopenharmony_ci */ 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci if (modified_VM() && modified_FILES() && modified_FS() && 281f08c3bdfSopenharmony_ci modified_SIG()) 282f08c3bdfSopenharmony_ci return 0; 283f08c3bdfSopenharmony_ci return -1; 284f08c3bdfSopenharmony_ci} 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_cistatic int parent_test2(void) 287f08c3bdfSopenharmony_ci{ 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci /* 290f08c3bdfSopenharmony_ci * For second test case (with no resouce shared), all of the 291f08c3bdfSopenharmony_ci * modified_*() functions should return 0 for parent_test2() 292f08c3bdfSopenharmony_ci * to return 1 293f08c3bdfSopenharmony_ci */ 294f08c3bdfSopenharmony_ci if (modified_VM() || modified_FILES() || modified_FS() || 295f08c3bdfSopenharmony_ci modified_SIG()) 296f08c3bdfSopenharmony_ci return 0; 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci return -1; 299f08c3bdfSopenharmony_ci} 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_ci/* 302f08c3bdfSopenharmony_ci * test_VM() - function to change parent_variable from child's 303f08c3bdfSopenharmony_ci * address space. If CLONE_VM flag is set, child shares 304f08c3bdfSopenharmony_ci * the memory space with parent so this will be visible 305f08c3bdfSopenharmony_ci * to parent also. 306f08c3bdfSopenharmony_ci */ 307f08c3bdfSopenharmony_ci 308f08c3bdfSopenharmony_cistatic int test_VM(void) 309f08c3bdfSopenharmony_ci{ 310f08c3bdfSopenharmony_ci parent_variable = CHILD_VALUE; 311f08c3bdfSopenharmony_ci return 0; 312f08c3bdfSopenharmony_ci} 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci/* 315f08c3bdfSopenharmony_ci * test_FILES() - This function closes a file descriptor opened by 316f08c3bdfSopenharmony_ci * parent. If CLONE_FILES flag is set, the parent and 317f08c3bdfSopenharmony_ci * the child process share the same file descriptor 318f08c3bdfSopenharmony_ci * table. so this affects the parent also 319f08c3bdfSopenharmony_ci */ 320f08c3bdfSopenharmony_cistatic int test_FILES(void) 321f08c3bdfSopenharmony_ci{ 322f08c3bdfSopenharmony_ci if (close(fd_parent) == -1) { 323f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "close failed in test_FILES"); 324f08c3bdfSopenharmony_ci return -1; 325f08c3bdfSopenharmony_ci } 326f08c3bdfSopenharmony_ci return 0; 327f08c3bdfSopenharmony_ci} 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_ci/* 330f08c3bdfSopenharmony_ci * test_FS() - This function changes the current working directory 331f08c3bdfSopenharmony_ci * of the child process. If CLONE_FS flag is set, this 332f08c3bdfSopenharmony_ci * will be visible to parent also. 333f08c3bdfSopenharmony_ci */ 334f08c3bdfSopenharmony_cistatic int test_FS(void) 335f08c3bdfSopenharmony_ci{ 336f08c3bdfSopenharmony_ci char *test_tmpdir; 337f08c3bdfSopenharmony_ci int rval; 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci test_tmpdir = tst_get_tmpdir(); 340f08c3bdfSopenharmony_ci if (test_tmpdir == NULL) { 341f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "tst_get_tmpdir failed"); 342f08c3bdfSopenharmony_ci rval = -1; 343f08c3bdfSopenharmony_ci } else if (chdir(test_tmpdir) == -1) { 344f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "chdir failed in test_FS"); 345f08c3bdfSopenharmony_ci rval = -1; 346f08c3bdfSopenharmony_ci } else { 347f08c3bdfSopenharmony_ci rval = 0; 348f08c3bdfSopenharmony_ci } 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci free(test_tmpdir); 351f08c3bdfSopenharmony_ci return rval; 352f08c3bdfSopenharmony_ci} 353f08c3bdfSopenharmony_ci 354f08c3bdfSopenharmony_ci/* 355f08c3bdfSopenharmony_ci * test_SIG() - This function changes the signal handler for SIGUSR2 356f08c3bdfSopenharmony_ci * signal for child. If CLONE_SIGHAND flag is set, this 357f08c3bdfSopenharmony_ci * affects parent also. 358f08c3bdfSopenharmony_ci */ 359f08c3bdfSopenharmony_cistatic int test_SIG(void) 360f08c3bdfSopenharmony_ci{ 361f08c3bdfSopenharmony_ci 362f08c3bdfSopenharmony_ci struct sigaction new_act; 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci new_act.sa_handler = sig_child_defined_handler; 365f08c3bdfSopenharmony_ci new_act.sa_flags = SA_RESTART; 366f08c3bdfSopenharmony_ci sigemptyset(&new_act.sa_mask); 367f08c3bdfSopenharmony_ci 368f08c3bdfSopenharmony_ci /* Set signal handler to sig_child_defined_handler */ 369f08c3bdfSopenharmony_ci if (sigaction(SIGUSR2, &new_act, NULL) == -1) { 370f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "signal failed in test_SIG"); 371f08c3bdfSopenharmony_ci return -1; 372f08c3bdfSopenharmony_ci } 373f08c3bdfSopenharmony_ci 374f08c3bdfSopenharmony_ci /* Send SIGUSR2 signal to parent */ 375f08c3bdfSopenharmony_ci if (kill(getppid(), SIGUSR2) == -1) { 376f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "kill failed in test_SIG"); 377f08c3bdfSopenharmony_ci return -1; 378f08c3bdfSopenharmony_ci } 379f08c3bdfSopenharmony_ci 380f08c3bdfSopenharmony_ci return 0; 381f08c3bdfSopenharmony_ci} 382f08c3bdfSopenharmony_ci 383f08c3bdfSopenharmony_ci/* 384f08c3bdfSopenharmony_ci * modified_VM() - This function is called by parent process to check 385f08c3bdfSopenharmony_ci * whether child's modification to parent_variable 386f08c3bdfSopenharmony_ci * is visible to parent 387f08c3bdfSopenharmony_ci */ 388f08c3bdfSopenharmony_ci 389f08c3bdfSopenharmony_cistatic int modified_VM(void) 390f08c3bdfSopenharmony_ci{ 391f08c3bdfSopenharmony_ci 392f08c3bdfSopenharmony_ci if (parent_variable == CHILD_VALUE) 393f08c3bdfSopenharmony_ci /* child has modified parent_variable */ 394f08c3bdfSopenharmony_ci return 1; 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci return 0; 397f08c3bdfSopenharmony_ci} 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci/* 400f08c3bdfSopenharmony_ci * modified_FILES() - This function checks for file descriptor table 401f08c3bdfSopenharmony_ci * modifications done by child 402f08c3bdfSopenharmony_ci */ 403f08c3bdfSopenharmony_cistatic int modified_FILES(void) 404f08c3bdfSopenharmony_ci{ 405f08c3bdfSopenharmony_ci char buff[20]; 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci if (((read(fd_parent, buff, sizeof(buff))) == -1) && (errno == EBADF)) 408f08c3bdfSopenharmony_ci /* Child has closed this file descriptor */ 409f08c3bdfSopenharmony_ci return 1; 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci /* close fd_parent */ 412f08c3bdfSopenharmony_ci if ((close(fd_parent)) == -1) 413f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "close() failed in modified_FILES()"); 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci return 0; 416f08c3bdfSopenharmony_ci} 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci/* 419f08c3bdfSopenharmony_ci * modified_FS() - This function checks parent's current working directory 420f08c3bdfSopenharmony_ci * to see whether its modified by child or not. 421f08c3bdfSopenharmony_ci */ 422f08c3bdfSopenharmony_cistatic int modified_FS(void) 423f08c3bdfSopenharmony_ci{ 424f08c3bdfSopenharmony_ci char cwd[FILENAME_MAX]; 425f08c3bdfSopenharmony_ci 426f08c3bdfSopenharmony_ci if ((getcwd(cwd, sizeof(cwd))) == NULL) 427f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "getcwd() failed"); 428f08c3bdfSopenharmony_ci 429f08c3bdfSopenharmony_ci if (!(strcmp(cwd, cwd_parent))) 430f08c3bdfSopenharmony_ci /* cwd hasn't changed */ 431f08c3bdfSopenharmony_ci return 0; 432f08c3bdfSopenharmony_ci 433f08c3bdfSopenharmony_ci return 1; 434f08c3bdfSopenharmony_ci} 435f08c3bdfSopenharmony_ci 436f08c3bdfSopenharmony_ci/* 437f08c3bdfSopenharmony_ci * modified_SIG() - This function checks whether child has changed 438f08c3bdfSopenharmony_ci * parent's signal handler for signal, SIGUSR2 439f08c3bdfSopenharmony_ci */ 440f08c3bdfSopenharmony_cistatic int modified_SIG(void) 441f08c3bdfSopenharmony_ci{ 442f08c3bdfSopenharmony_ci 443f08c3bdfSopenharmony_ci if (parent_got_signal) 444f08c3bdfSopenharmony_ci /* 445f08c3bdfSopenharmony_ci * parent came through sig_child_defined_handler() 446f08c3bdfSopenharmony_ci * this means child has changed parent's handler 447f08c3bdfSopenharmony_ci */ 448f08c3bdfSopenharmony_ci return 1; 449f08c3bdfSopenharmony_ci 450f08c3bdfSopenharmony_ci return 0; 451f08c3bdfSopenharmony_ci} 452f08c3bdfSopenharmony_ci 453f08c3bdfSopenharmony_ci/* 454f08c3bdfSopenharmony_ci * sig_child_defined_handler() - Signal handler installed by child 455f08c3bdfSopenharmony_ci */ 456f08c3bdfSopenharmony_cistatic void sig_child_defined_handler(int pid) 457f08c3bdfSopenharmony_ci{ 458f08c3bdfSopenharmony_ci if ((syscall(__NR_gettid)) == child_pid) 459f08c3bdfSopenharmony_ci /* Child got signal, give warning */ 460f08c3bdfSopenharmony_ci tst_resm(TWARN, "Child got SIGUSR2 signal"); 461f08c3bdfSopenharmony_ci else 462f08c3bdfSopenharmony_ci parent_got_signal = TRUE; 463f08c3bdfSopenharmony_ci} 464f08c3bdfSopenharmony_ci 465f08c3bdfSopenharmony_ci/* sig_default_handler() - Default handler for parent */ 466f08c3bdfSopenharmony_cistatic void sig_default_handler(void) 467f08c3bdfSopenharmony_ci{ 468f08c3bdfSopenharmony_ci} 469