Home | History | Annotate | Download | only in shmt
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2002
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program 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
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;  if not, write to the Free Software
     17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /* 12/20/2002   Port to LTP     robbiew (at) us.ibm.com */
     21 /* 06/30/2001   Port to Linux   nsharoff (at) us.ibm.com */
     22 
     23 /*
     24  * NAME
     25  *	shmt06
     26  *
     27  * CALLS
     28  *	shmctl(2) shmget(2) shmat(2)
     29  *
     30  * ALGORITHM
     31  * Parent process forks a child. Child pauses until parent has created
     32  * a shared memory segment, attached to it and written to it too. At that
     33  * time child gets the shared memory segment id, attaches to it at two
     34  * different addresses than the parents and verifies that their contents
     35  * are the same as the contents of the parent attached segment.
     36  *
     37  */
     38 
     39 #include <stdio.h>
     40 #include <sys/types.h>
     41 #include <sys/wait.h>
     42 #include <sys/ipc.h>
     43 #include <sys/shm.h>
     44 #include <sys/utsname.h>
     45 #include <signal.h>
     46 #include <errno.h>
     47 #include <stdlib.h>
     48 #include <unistd.h>
     49 
     50 #define		SIZE		16*1024
     51 
     52 /** LTP Port **/
     53 #include "test.h"
     54 
     55 char *TCID = "shmt06";		/* Test program identifier.    */
     56 int TST_TOTAL = 2;		/* Total number of test cases. */
     57 /**************/
     58 
     59 key_t key;
     60 sigset_t set;
     61 
     62 int child();
     63 static int rm_shm(int);
     64 
     65 int main(void)
     66 {
     67 	char *cp = NULL;
     68 	int pid, pid1, shmid;
     69 	int status;
     70 
     71 	key = (key_t) getpid();
     72 
     73 	sigemptyset(&set);
     74 	sigaddset(&set, SIGUSR1);
     75 	sigprocmask(SIG_BLOCK, &set, NULL);
     76 
     77 	pid = fork();
     78 	switch (pid) {
     79 	case -1:
     80 		tst_brkm(TBROK, NULL, "fork failed");
     81 	case 0:
     82 		child();
     83 	}
     84 
     85 /*------------------------------------------------------*/
     86 
     87 	if ((shmid = shmget(key, SIZE, IPC_CREAT | 0666)) < 0) {
     88 		perror("shmget");
     89 		tst_resm(TFAIL, "Error: shmget: shmid = %d, errno = %d\n",
     90 			 shmid, errno);
     91 		/*
     92 		 * kill the child if parent failed to do the attach
     93 		 */
     94 		(void)kill(pid, SIGINT);
     95 	} else {
     96 		cp = shmat(shmid, NULL, 0);
     97 
     98 		if (cp == (char *)-1) {
     99 			perror("shmat");
    100 			tst_resm(TFAIL,
    101 				 "Error: shmat: shmid = %d, errno = %d\n",
    102 				 shmid, errno);
    103 
    104 			/* kill the child if parent failed to do the attch */
    105 
    106 			kill(pid, SIGINT);
    107 
    108 			/* remove shared memory segment */
    109 
    110 			rm_shm(shmid);
    111 
    112 			tst_exit();
    113 		}
    114 		*cp = 'A';
    115 		*(cp + 1) = 'B';
    116 		*(cp + 2) = 'C';
    117 
    118 		kill(pid, SIGUSR1);
    119 		while ((pid1 = wait(&status)) < 0 && (errno == EINTR)) ;
    120 		if (pid1 != pid) {
    121 			tst_resm(TFAIL, "Waited on the wrong child");
    122 			tst_resm(TFAIL,
    123 				 "Error: wait_status = %d, pid1= %d\n", status,
    124 				 pid1);
    125 		}
    126 	}
    127 
    128 	tst_resm(TPASS, "shmget,shmat");
    129 
    130 /*---------------------------------------------------------------*/
    131 
    132 	if (shmdt(cp) < 0) {
    133 		tst_resm(TFAIL, "shmdt");
    134 	}
    135 
    136 	tst_resm(TPASS, "shmdt");
    137 
    138 /*-------------------------------------------------------------*/
    139 
    140 	rm_shm(shmid);
    141 	tst_exit();
    142 }
    143 
    144 int child(void)
    145 {
    146 	int shmid, chld_pid;
    147 	char *cp;
    148 	int sig;
    149 
    150 	sigwait(&set, &sig);
    151 	chld_pid = getpid();
    152 
    153 	if ((shmid = shmget(key, SIZE, 0)) < 0) {
    154 		perror("shmget:child process");
    155 		tst_resm(TFAIL,
    156 			 "Error: shmget: errno=%d, shmid=%d, child_pid=%d\n",
    157 			 errno, shmid, chld_pid);
    158 	} else {
    159 		cp = shmat(shmid, NULL, 0);
    160 
    161 		if (cp == (char *)-1) {
    162 			perror("shmat:child process");
    163 			tst_resm(TFAIL,
    164 				 "Error: shmat: errno=%d, shmid=%d, child_pid=%d\n",
    165 				 errno, shmid, chld_pid);
    166 		} else {
    167 			if (*cp != 'A') {
    168 				tst_resm(TFAIL, "child: not A\n");
    169 			}
    170 			if (*(cp + 1) != 'B') {
    171 				tst_resm(TFAIL, "child: not B\n");
    172 			}
    173 			if (*(cp + 2) != 'C') {
    174 				tst_resm(TFAIL, "child: not C\n");
    175 			}
    176 			if (*(cp + 8192) != 0) {
    177 				tst_resm(TFAIL, "child: not 0\n");
    178 			}
    179 		}
    180 
    181 		/*
    182 		 * Attach the segment to a different addresse
    183 		 * and verify it's contents again.
    184 		 */
    185 		cp = shmat(shmid, NULL, 0);
    186 
    187 		if (cp == (char *)-1) {
    188 			perror("shmat:child process");
    189 			tst_resm(TFAIL,
    190 				 "Error: shmat: errno=%d, shmid=%d, child_pid=%d\n",
    191 				 errno, shmid, chld_pid);
    192 		} else {
    193 			if (*cp != 'A') {
    194 				tst_resm(TFAIL, "child: not A\n");
    195 			}
    196 			if (*(cp + 1) != 'B') {
    197 				tst_resm(TFAIL, "child: not B\n");
    198 			}
    199 			if (*(cp + 2) != 'C') {
    200 				tst_resm(TFAIL, "child: not C\n");
    201 			}
    202 			if (*(cp + 8192) != 0) {
    203 				tst_resm(TFAIL, "child: not 0\n");
    204 			}
    205 		}
    206 	}
    207 	tst_exit();
    208 }
    209 
    210 static int rm_shm(int shmid)
    211 {
    212 	if (shmctl(shmid, IPC_RMID, NULL) == -1) {
    213 		perror("shmctl");
    214 		tst_brkm(TFAIL,
    215 			 NULL,
    216 			 "shmctl Failed to remove: shmid = %d, errno = %d\n",
    217 			 shmid, errno);
    218 	}
    219 	return (0);
    220 }
    221