blob: ba3acfa35d072faea4e179125dc53a7e8ec58efb [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
22 * msgsnd05.c
23 *
24 * DESCRIPTION
25 * msgsnd05 - test for EINTR error
26 *
27 * ALGORITHM
28 * create a message queue with read/write permissions
29 * initialize a message buffer with a known message and type
30 * enqueue the message in a loop until the queue is full
31 * loop if that option was specified
32 * fork a child process
33 * child attempts to enqueue a message to the full queue and sleeps
robbiewd34d5812005-07-11 22:28:09 +000034 * parent sends a SIGHUP to the child then waits for the child to complete
plars865695b2001-08-27 22:15:12 +000035 * child get a return from msgsnd()
36 * check the errno value
37 * issue a PASS message if we get EINTR
38 * otherwise, the tests fails
39 * issue a FAIL message
robbiewd34d5812005-07-11 22:28:09 +000040 * child exits, parent calls cleanup
plars865695b2001-08-27 22:15:12 +000041 *
42 * USAGE: <for command-line>
43 * msgsnd05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
44 * where, -c n : Run n copies concurrently.
45 * -e : Turn on errno logging.
46 * -i n : Execute test n times.
47 * -I x : Execute test for x seconds.
48 * -P x : Pause for x seconds between iterations.
49 * -t : Turn on syscall timing.
50 *
51 * HISTORY
52 * 03/2001 - Written by Wayne Boyer
subrata_modake8d78ce2008-04-06 11:52:07 +000053 * 14/03/2008 Matthieu Fertré (Matthieu.Fertre@irisa.fr)
54 * - Fix concurrency issue. Due to the use of usleep function to
55 * synchronize processes, synchronization issues can occur on a loaded
56 * system. Fix this by using pipes to synchronize processes.
plars865695b2001-08-27 22:15:12 +000057 *
58 * RESTRICTIONS
59 * none
60 */
61
62#include "test.h"
plars865695b2001-08-27 22:15:12 +000063
robbiew23499f02002-11-18 19:54:58 +000064#include "ipcmsg.h"
subrata_modake8d78ce2008-04-06 11:52:07 +000065#include "libtestsuite.h"
plars865695b2001-08-27 22:15:12 +000066
robbiewd34d5812005-07-11 22:28:09 +000067#include <sys/types.h>
68#include <sys/wait.h>
69
70void do_child(void);
plars865695b2001-08-27 22:15:12 +000071void cleanup(void);
72void setup(void);
robbiewd34d5812005-07-11 22:28:09 +000073#ifdef UCLINUX
subrata_modak4b13c892009-01-22 09:51:33 +000074#define PIPE_NAME "msgsnd05"
robbiewd34d5812005-07-11 22:28:09 +000075void do_child_uclinux(void);
76#endif
plars865695b2001-08-27 22:15:12 +000077
78char *TCID = "msgsnd05";
79int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000080
plars865695b2001-08-27 22:15:12 +000081int msg_q_1 = -1; /* The message queue id created in setup */
subrata_modak4b13c892009-01-22 09:51:33 +000082
83int sync_pipes[2];
84
plars865695b2001-08-27 22:15:12 +000085MSGBUF msg_buf;
86
robbiew23499f02002-11-18 19:54:58 +000087int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000088{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020089 int lc;
Cyril Hrubis74225622014-06-02 17:54:38 +020090 const char *msg;
robbiew23499f02002-11-18 19:54:58 +000091 pid_t c_pid;
plars865695b2001-08-27 22:15:12 +000092
Cyril Hrubis74225622014-06-02 17:54:38 +020093 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080094 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Cyril Hrubis74225622014-06-02 17:54:38 +020095
robbiewd34d5812005-07-11 22:28:09 +000096#ifdef UCLINUX
97 maybe_run_child(&do_child_uclinux, "d", &msg_q_1);
98#endif
99
subrata_modak56207ce2009-03-23 13:35:39 +0000100 setup(); /* global setup */
plars865695b2001-08-27 22:15:12 +0000101
subrata_modak4b13c892009-01-22 09:51:33 +0000102 if (sync_pipe_create(sync_pipes, PIPE_NAME) == -1)
subrata_modak8791f672008-05-20 10:11:00 +0000103 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
subrata_modake8d78ce2008-04-06 11:52:07 +0000104
plars865695b2001-08-27 22:15:12 +0000105 /* The following loop checks looping state if -i option given */
106
107 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800108 /* reset tst_count in case we are looping */
109 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000110
111 /*
112 * fork a child that will attempt to write a message
113 * to the queue without IPC_NOWAIT
114 */
robbiewd34d5812005-07-11 22:28:09 +0000115 if ((c_pid = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000116 tst_brkm(TBROK, cleanup, "could not fork");
117 }
118
subrata_modak56207ce2009-03-23 13:35:39 +0000119 if (c_pid == 0) { /* child */
plars865695b2001-08-27 22:15:12 +0000120 /*
121 * Attempt to write another message to the full queue.
122 * Without the IPC_NOWAIT flag, the child sleeps
123 */
subrata_modake8d78ce2008-04-06 11:52:07 +0000124
robbiewd34d5812005-07-11 22:28:09 +0000125#ifdef UCLINUX
126 if (self_exec(av[0], "d", msg_q_1) < 0) {
127 tst_brkm(TBROK, cleanup, "could not self_exec");
128 }
129#else
130 do_child();
131#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000132 } else { /* parent */
subrata_modake8d78ce2008-04-06 11:52:07 +0000133
subrata_modak8791f672008-05-20 10:11:00 +0000134 if (sync_pipe_wait(sync_pipes) == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000135 tst_brkm(TBROK, cleanup,
136 "sync_pipe_wait failed");
subrata_modak8791f672008-05-20 10:11:00 +0000137
subrata_modak4b13c892009-01-22 09:51:33 +0000138 if (sync_pipe_close(sync_pipes, PIPE_NAME) == -1)
subrata_modak56207ce2009-03-23 13:35:39 +0000139 tst_brkm(TBROK, cleanup,
140 "sync_pipe_close failed");
subrata_modak8791f672008-05-20 10:11:00 +0000141
subrata_modake8d78ce2008-04-06 11:52:07 +0000142 /* After son has been created, give it a chance to execute the
143 * msgsnd command before we continue. Without this sleep, on SMP machine
144 * the father kill could be executed before the son msgsnd.
145 */
146 sleep(2);
plars865695b2001-08-27 22:15:12 +0000147
148 /* send a signal that must be caught to the child */
149 if (kill(c_pid, SIGHUP) == -1) {
150 tst_brkm(TBROK, cleanup, "kill failed");
151 }
152
robbiewd34d5812005-07-11 22:28:09 +0000153 waitpid(c_pid, NULL, 0);
plars865695b2001-08-27 22:15:12 +0000154 }
155 }
156
157 cleanup();
158
Garrett Cooper7d0a4a52010-12-16 10:05:08 -0800159 tst_exit();
plars865695b2001-08-27 22:15:12 +0000160}
161
162/*
robbiewd34d5812005-07-11 22:28:09 +0000163 * do_child()
164 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400165void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000166{
subrata_modak4b13c892009-01-22 09:51:33 +0000167 if (sync_pipe_notify(sync_pipes) == -1)
168 tst_brkm(TBROK, cleanup, "sync_pipe_notify failed");
169
170 if (sync_pipe_close(sync_pipes, PIPE_NAME) == -1)
171 tst_brkm(TBROK, cleanup, "sync_pipe_close failed");
172
robbiewd34d5812005-07-11 22:28:09 +0000173 TEST(msgsnd(msg_q_1, &msg_buf, MSGSIZE, 0));
174
175 if (TEST_RETURN != -1) {
176 tst_resm(TFAIL, "call succeeded when error expected");
177 exit(-1);
178 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000179
subrata_modak56207ce2009-03-23 13:35:39 +0000180 switch (TEST_ERRNO) {
robbiewd34d5812005-07-11 22:28:09 +0000181 case EINTR:
182 tst_resm(TPASS, "expected failure - errno = %d : %s",
183 TEST_ERRNO, strerror(TEST_ERRNO));
184 break;
185 default:
subrata_modak56207ce2009-03-23 13:35:39 +0000186 tst_resm(TFAIL,
187 "call failed with an unexpected error - %d : %s",
robbiewd34d5812005-07-11 22:28:09 +0000188 TEST_ERRNO, strerror(TEST_ERRNO));
189 break;
190 }
191
192 exit(0);
193}
194
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195void sighandler(int sig)
Garrett Cooper6be4ba42010-12-20 15:50:04 -0800196{
197 if (sig == SIGHUP)
198 return;
199 else
200 tst_brkm(TBROK, NULL, "received unexpected signal %d", sig);
201}
202
robbiewd34d5812005-07-11 22:28:09 +0000203#ifdef UCLINUX
204/*
205 * do_child_uclinux() - capture signals, initialize buffer, then run do_child()
206 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400207void do_child_uclinux(void)
robbiewd34d5812005-07-11 22:28:09 +0000208{
209 /* initialize the message buffer */
210 init_buf(&msg_buf, MSGTYPE, MSGSIZE);
211
subrata_modak4b13c892009-01-22 09:51:33 +0000212 if (sync_pipe_create(sync_pipes, PIPE_NAME) == -1)
213 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
214
Garrett Cooper6be4ba42010-12-20 15:50:04 -0800215 tst_sig(FORK, sighandler, cleanup);
robbiewd34d5812005-07-11 22:28:09 +0000216
217 do_child();
218}
219#endif
220
221/*
plars865695b2001-08-27 22:15:12 +0000222 * setup() - performs all the ONE TIME setup for this test.
223 */
subrata_modak56207ce2009-03-23 13:35:39 +0000224void setup(void)
plars865695b2001-08-27 22:15:12 +0000225{
226 /* capture signals in our own handler */
Garrett Cooper6be4ba42010-12-20 15:50:04 -0800227 tst_sig(FORK, sighandler, cleanup);
plars865695b2001-08-27 22:15:12 +0000228
plars865695b2001-08-27 22:15:12 +0000229 TEST_PAUSE;
230
231 /*
232 * Create a temporary directory and cd into it.
233 * This helps to ensure that a unique msgkey is created.
234 * See ../lib/libipc.c for more information.
235 */
236 tst_tmpdir();
237
238 msgkey = getipckey();
239
240 /* create a message queue with read/write permission */
241 if ((msg_q_1 = msgget(msgkey, IPC_CREAT | IPC_EXCL | MSG_RW)) == -1) {
242 tst_brkm(TBROK, cleanup, "Can't create message queue");
243 }
244
245 /* initialize the message buffer */
246 init_buf(&msg_buf, MSGTYPE, MSGSIZE);
247
248 /* write messages to the queue until it is full */
249 while (msgsnd(msg_q_1, &msg_buf, MSGSIZE, IPC_NOWAIT) != -1) {
250 msg_buf.mtype += 1;
251 }
252}
253
254/*
255 * cleanup() - performs all the ONE TIME cleanup for this test at completion
256 * or premature exit.
257 */
subrata_modak56207ce2009-03-23 13:35:39 +0000258void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000259{
260 /* if it exists, remove the message queue that was created */
261 rm_queue(msg_q_1);
262
plars865695b2001-08-27 22:15:12 +0000263 tst_rmdir();
264
Garrett Cooper52626672010-12-20 15:03:21 -0800265}