• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
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 /*
21  * NAME
22  *	shmdt01.c
23  *
24  * DESCRIPTION
25  *	shmdt01 - check that shared memory is detached correctly
26  *
27  * ALGORITHM
28  *	create a shared memory resource of size sizeof(int)
29  *	attach it to the current process and give it a value
30  *	call shmdt() using the TEST macro
31  *	check the return code
32  *	  if failure, issue a FAIL message.
33  *	otherwise,
34  *	  if doing functionality testing
35  *		attempt to write a value to the shared memory address
36  *		this should generate a SIGSEGV which will be caught in
37  *		    the signal handler
38  *	  	if correct,
39  *			issue a PASS message
40  *		otherwise
41  *			issue a FAIL message
42  *	call cleanup
43  *
44  * USAGE:  <for command-line>
45  *  shmdt01 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
46  *     where,  -c n : Run n copies concurrently.
47  *             -f   : Turn off functionality Testing.
48  *	       -I x : Execute test for x seconds.
49  *	       -P x : Pause for x seconds between iterations.
50  *	       -t   : Turn on syscall timing.
51  *
52  * HISTORY
53  *	03/2001 - Written by Wayne Boyer
54  *
55  *      06/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
56  *      - Fix wrong return value check on shmat system call (leading to
57  *        segfault in case of error with this syscall).
58  *
59  * RESTRICTIONS
60  *	none
61  */
62 
63 #include <setjmp.h>
64 #include "ipcshm.h"
65 
66 char *TCID = "shmdt01";
67 int TST_TOTAL = 1;
68 
69 void sighandler(int);
70 struct shmid_ds buf;
71 
72 int shm_id_1 = -1;
73 int *shared;			/* variable to use for shared memory attach */
74 int new;
75 int pass = 0;
76 sigjmp_buf env;
77 
main(int ac,char ** av)78 int main(int ac, char **av)
79 {
80 	int lc;
81 	void check_functionality(void);
82 
83 	tst_parse_opts(ac, av, NULL, NULL);
84 
85 	setup();		/* global setup */
86 
87 	/* The following loop checks looping state if -i option given */
88 
89 	for (lc = 0; TEST_LOOPING(lc); lc++) {
90 		/* reset tst_count in case we are looping */
91 		tst_count = 0;
92 
93 		/*
94 		 * Use TEST macro to make the shmdt() call
95 		 */
96 
97 		TEST(shmdt((const void *)shared));
98 
99 		if (TEST_RETURN == -1) {
100 			tst_resm(TFAIL, "%s call failed - errno = %d : %s",
101 				 TCID, TEST_ERRNO, strerror(TEST_ERRNO));
102 		} else {
103 			check_functionality();
104 		}
105 
106 		/* reattach the shared memory segment in case we are looping */
107 		shared = shmat(shm_id_1, 0, 0);
108 
109 		if (shared == (void *)-1) {
110 			tst_brkm(TBROK, cleanup, "memory reattach failed");
111 		}
112 
113 		/* also reset pass */
114 		pass = 0;
115 	}
116 
117 	cleanup();
118 
119 	tst_exit();
120 }
121 
122 /*
123  * check_functionality() - make sure the memory is detached correctly
124  */
check_functionality(void)125 void check_functionality(void)
126 {
127 	/* stat the shared memory segment */
128 	if (shmctl(shm_id_1, IPC_STAT, &buf) == -1)
129 		tst_brkm(TBROK | TERRNO, cleanup,
130 			 "could not stat in signal handler");
131 
132 	if (buf.shm_nattch != 0) {
133 		tst_resm(TFAIL, "# of attaches is incorrect");
134 		return;
135 	}
136 
137 	/*
138 	 * Try writing to the shared memory.  This should generate a
139 	 * SIGSEGV which will be caught below.
140 	 *
141 	 * This is wrapped by the sigsetjmp() call that will take care of
142 	 * restoring the program's context in an elegant way in conjunction
143 	 * with the call to siglongjmp() in the signal handler.
144 	 *
145 	 * An attempt to do the assignment without using the sigsetjmp()
146 	 * and siglongjmp() calls will result in an infinite loop.  Program
147 	 * control is returned to the assignment statement after the execution
148 	 * of the signal handler and another SIGSEGV will be generated.
149 	 */
150 
151 	if (sigsetjmp(env, 1) == 0) {
152 		*shared = 2;
153 	}
154 
155 	if (pass) {
156 		tst_resm(TPASS, "shared memory detached correctly");
157 	} else {
158 		tst_resm(TFAIL, "shared memory was not detached correctly");
159 	}
160 }
161 
sighandler(int sig)162 void sighandler(int sig)
163 {
164 	/* if we have received a SIGSEGV, we are almost done */
165 	if (sig == SIGSEGV) {
166 		/* set the global variable and jump back */
167 		pass = 1;
168 		siglongjmp(env, 1);
169 	} else
170 		tst_brkm(TBROK, cleanup,
171 			 "received an unexpected signal: %d", sig);
172 }
173 
174 /*
175  * setup() - performs all the ONE TIME setup for this test.
176  */
setup(void)177 void setup(void)
178 {
179 
180 	tst_sig(NOFORK, sighandler, cleanup);
181 
182 	TEST_PAUSE;
183 
184 	/*
185 	 * Create a temporary directory and cd into it.
186 	 * This helps to ensure that a unique msgkey is created.
187 	 * See ../lib/libipc.c for more information.
188 	 */
189 	tst_tmpdir();
190 
191 	/* get an IPC resource key */
192 	shmkey = getipckey();
193 
194 	/* create a shared memory resource with read and write permissions */
195 	if ((shm_id_1 = shmget(shmkey, INT_SIZE, SHM_RW | IPC_CREAT |
196 			       IPC_EXCL)) == -1) {
197 		tst_brkm(TBROK, cleanup, "Failed to create shared memory "
198 			 "resource in setup()");
199 	}
200 
201 	/* attach the shared memory segment */
202 	shared = shmat(shm_id_1, 0, 0);
203 
204 	if (shared == (void *)-1) {
205 		tst_brkm(TBROK, cleanup, "Couldn't attach shared memory");
206 	}
207 
208 	/* give a value to the shared memory integer */
209 	*shared = 4;
210 }
211 
212 /*
213  * cleanup() - performs all the ONE TIME cleanup for this test at completion
214  * 	       or premature exit.
215  */
cleanup(void)216 void cleanup(void)
217 {
218 	/* if it exists, delete the shared memory resource */
219 	rm_shm(shm_id_1);
220 
221 	tst_rmdir();
222 
223 }
224