blob: 73b781dd9958b67a9dc6afd756699b2c1c8ee38a [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
subrata_modak56207ce2009-03-23 13:35:39 +000022 * fcntl17.c
plars865695b2001-08-27 22:15:12 +000023 *
24 * DESCRIPTION
subrata_modak56207ce2009-03-23 13:35:39 +000025 * Check deadlock detection for file locking
plars865695b2001-08-27 22:15:12 +000026 *
27 * ALGORITHM
subrata_modak56207ce2009-03-23 13:35:39 +000028 * The parent forks off 3 children. The parent controls the children
29 * with messages via pipes to create a delayed deadlock between the
30 * second and third child.
plars865695b2001-08-27 22:15:12 +000031 *
32 * USAGE
subrata_modak56207ce2009-03-23 13:35:39 +000033 * fcntl17
plars865695b2001-08-27 22:15:12 +000034 *
35 * HISTORY
36 * 07/2001 Ported by Wayne Boyer
subrata_modak4bb656a2009-02-26 12:02:09 +000037 * 04/2002 Minor fixes by William Jay Huie (testcase name
plars07635bc2002-04-18 16:26:43 +000038 fcntl05 => fcntl17, check signal return for SIG_ERR)
plars865695b2001-08-27 22:15:12 +000039 *
40 * RESTRICTIONS
41 * None
42 */
43
vapier5b31d1b2006-08-21 06:46:26 +000044#ifndef _GNU_SOURCE
Wanlong Gao354ebb42012-12-07 10:10:04 +080045#define _GNU_SOURCE
vapier5b31d1b2006-08-21 06:46:26 +000046#endif
47
plars865695b2001-08-27 22:15:12 +000048#include <fcntl.h>
49#include <errno.h>
50#include <signal.h>
robbiew5aab8a72003-03-26 18:05:30 +000051#include <sys/stat.h>
52#include <sys/types.h>
mridgedb639212005-01-04 21:04:11 +000053#include <sys/wait.h>
subrata_modak923b23f2009-11-02 13:57:16 +000054#include <inttypes.h>
55
robbiew5aab8a72003-03-26 18:05:30 +000056#include "test.h"
plars865695b2001-08-27 22:15:12 +000057
plars07635bc2002-04-18 16:26:43 +000058char *TCID = "fcntl17";
plars865695b2001-08-27 22:15:12 +000059int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000060
61#define STRINGSIZE 27
62#define STRING "abcdefghijklmnopqrstuvwxyz\n"
63#define STOP 0xFFF0
64#define TIME_OUT 10
65
66/* global variables */
67int parent_pipe[2];
68int child_pipe1[2];
69int child_pipe2[2];
70int child_pipe3[2];
71int file_fd;
robbiew46736852003-03-13 15:43:49 +000072pid_t parent_pid, child_pid1, child_pid2, child_pid3;
plars874b4222002-04-18 17:19:16 +000073int child_stat;
subrata_modak56207ce2009-03-23 13:35:39 +000074struct flock lock1 = { (short)F_WRLCK, (short)0, 2, 5, (short)0 };
75struct flock lock2 = { (short)F_WRLCK, (short)0, 9, 5, (short)0 };
76struct flock lock3 = { (short)F_WRLCK, (short)0, 17, 5, (short)0 };
77struct flock lock4 = { (short)F_WRLCK, (short)0, 17, 5, (short)0 };
78struct flock lock5 = { (short)F_WRLCK, (short)0, 2, 14, (short)0 };
79struct flock unlock = { (short)F_UNLCK, (short)0, 0, 0, (short)0 };
plars865695b2001-08-27 22:15:12 +000080
81/* prototype declarations */
82int setup();
83void cleanup();
84int parent_wait();
85void parent_free();
86void child_wait();
87void child_free();
88void do_child1();
89void do_child2();
90void do_child3();
subrata_modakf08488f2008-11-18 09:38:10 +000091int do_test(struct flock *, pid_t);
plars865695b2001-08-27 22:15:12 +000092void stop_children();
93void catch_child();
94void catch_alarm();
95char *str_type();
96
Mike Frysingerc57fba52014-04-09 18:56:30 -040097int setup(void)
plars865695b2001-08-27 22:15:12 +000098{
99 char *buf = STRING;
subrata_modak56207ce2009-03-23 13:35:39 +0000100 char template[PATH_MAX];
robbiew1e4cf0c2005-02-24 17:03:42 +0000101 struct sigaction act;
plars865695b2001-08-27 22:15:12 +0000102
Garrett Cooper2c282152010-12-16 00:55:50 -0800103 tst_sig(FORK, DEF_HANDLER, NULL);
plars865695b2001-08-27 22:15:12 +0000104 umask(0);
Garrett Cooper2c282152010-12-16 00:55:50 -0800105 TEST_PAUSE;
subrata_modak56207ce2009-03-23 13:35:39 +0000106 tst_tmpdir(); /* make temp dir and cd to it */
plars865695b2001-08-27 22:15:12 +0000107
subrata_modak56207ce2009-03-23 13:35:39 +0000108 if (pipe(parent_pipe) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000109 tst_resm(TFAIL, "Couldn't create parent_pipe! errno = %d",
plarscaccaf22002-04-18 16:39:41 +0000110 errno);
subrata_modak134e8962009-02-26 11:46:54 +0000111 return 1;
plarscaccaf22002-04-18 16:39:41 +0000112 }
subrata_modak56207ce2009-03-23 13:35:39 +0000113 if (pipe(child_pipe1) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000114 tst_resm(TFAIL, "Couldn't create child_pipe1! errno = %d",
plarscaccaf22002-04-18 16:39:41 +0000115 errno);
subrata_modak134e8962009-02-26 11:46:54 +0000116 return 1;
plarscaccaf22002-04-18 16:39:41 +0000117 }
subrata_modak56207ce2009-03-23 13:35:39 +0000118 if (pipe(child_pipe2) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000119 tst_resm(TFAIL, "Couldn't create child_pipe2! errno = %d",
plarscaccaf22002-04-18 16:39:41 +0000120 errno);
subrata_modak134e8962009-02-26 11:46:54 +0000121 return 1;
plarscaccaf22002-04-18 16:39:41 +0000122 }
subrata_modak56207ce2009-03-23 13:35:39 +0000123 if (pipe(child_pipe3) < 0) {
subrata_modak4bb656a2009-02-26 12:02:09 +0000124 tst_resm(TFAIL, "Couldn't create child_pipe3! errno = %d",
plarscaccaf22002-04-18 16:39:41 +0000125 errno);
subrata_modak134e8962009-02-26 11:46:54 +0000126 return 1;
plarscaccaf22002-04-18 16:39:41 +0000127 }
plars865695b2001-08-27 22:15:12 +0000128 parent_pid = getpid();
robbiewdad22712003-04-16 19:14:05 +0000129 snprintf(template, PATH_MAX, "fcntl17XXXXXX");
plars865695b2001-08-27 22:15:12 +0000130
subrata_modak56207ce2009-03-23 13:35:39 +0000131 if ((file_fd = mkstemp(template)) < 0) {
132 tst_resm(TFAIL, "Couldn't open temp file! errno = %d", errno);
133 }
plars865695b2001-08-27 22:15:12 +0000134
subrata_modak56207ce2009-03-23 13:35:39 +0000135 if (write(file_fd, buf, STRINGSIZE) < 0) {
136 tst_resm(TFAIL, "Couldn't write to temp file! errno = %d",
137 errno);
138 }
plars865695b2001-08-27 22:15:12 +0000139
robbiew1e4cf0c2005-02-24 17:03:42 +0000140 memset(&act, 0, sizeof(act));
141 act.sa_handler = catch_alarm;
142 sigemptyset(&act.sa_mask);
143 sigaddset(&act.sa_mask, SIGALRM);
144 if (sigaction(SIGALRM, &act, NULL) < 0) {
plars865695b2001-08-27 22:15:12 +0000145 tst_resm(TFAIL, "SIGALRM signal setup failed, errno: %d",
146 errno);
subrata_modak134e8962009-02-26 11:46:54 +0000147 return 1;
plars865695b2001-08-27 22:15:12 +0000148 }
149
robbiew1e4cf0c2005-02-24 17:03:42 +0000150 memset(&act, 0, sizeof(act));
151 act.sa_handler = catch_child;
152 sigemptyset(&act.sa_mask);
153 sigaddset(&act.sa_mask, SIGCLD);
154 if (sigaction(SIGCLD, &act, NULL) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000155 tst_resm(TFAIL, "SIGCLD signal setup failed, errno: %d", errno);
subrata_modak134e8962009-02-26 11:46:54 +0000156 return 1;
plars865695b2001-08-27 22:15:12 +0000157 }
subrata_modak43337a32009-02-26 11:43:51 +0000158 return 0;
plars865695b2001-08-27 22:15:12 +0000159}
160
Mike Frysingerc57fba52014-04-09 18:56:30 -0400161void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000162{
subrata_modak56207ce2009-03-23 13:35:39 +0000163 close(file_fd);
plars865695b2001-08-27 22:15:12 +0000164 tst_rmdir();
Garrett Cooper2c282152010-12-16 00:55:50 -0800165
plars865695b2001-08-27 22:15:12 +0000166}
167
Mike Frysingerc57fba52014-04-09 18:56:30 -0400168void do_child1(void)
plars865695b2001-08-27 22:15:12 +0000169{
subrata_modak56207ce2009-03-23 13:35:39 +0000170 int err;
mridgedb639212005-01-04 21:04:11 +0000171
plars865695b2001-08-27 22:15:12 +0000172 close(parent_pipe[0]);
173 close(child_pipe1[1]);
174 close(child_pipe2[0]);
175 close(child_pipe2[1]);
176 close(child_pipe3[0]);
177 close(child_pipe3[1]);
178
179 child_wait(child_pipe1[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000180 tst_resm(TINFO, "child 1 starting");
plars865695b2001-08-27 22:15:12 +0000181 if (fcntl(file_fd, F_SETLK, &lock1) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000182 err = errno;
183 tst_resm(TINFO, "child 1 lock err %d", err);
mridgedb639212005-01-04 21:04:11 +0000184 parent_free(err);
plars865695b2001-08-27 22:15:12 +0000185 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000186 tst_resm(TINFO, "child 1 pid %d locked", getpid());
plars865695b2001-08-27 22:15:12 +0000187 parent_free(0);
188 }
189
190 child_wait(child_pipe1[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000191 tst_resm(TINFO, "child 1 resuming");
plars865695b2001-08-27 22:15:12 +0000192 fcntl(file_fd, F_SETLK, &unlock);
subrata_modak56207ce2009-03-23 13:35:39 +0000193 tst_resm(TINFO, "child 1 unlocked");
plars865695b2001-08-27 22:15:12 +0000194
195 child_wait(child_pipe1[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000196 tst_resm(TINFO, "child 1 exiting");
plars865695b2001-08-27 22:15:12 +0000197 exit(1);
198}
199
Mike Frysingerc57fba52014-04-09 18:56:30 -0400200void do_child2(void)
plars865695b2001-08-27 22:15:12 +0000201{
subrata_modak56207ce2009-03-23 13:35:39 +0000202 int err;
mridgedb639212005-01-04 21:04:11 +0000203
plars865695b2001-08-27 22:15:12 +0000204 close(parent_pipe[0]);
205 close(child_pipe1[0]);
206 close(child_pipe1[1]);
207 close(child_pipe2[1]);
208 close(child_pipe3[0]);
209 close(child_pipe3[1]);
210
211 child_wait(child_pipe2[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000212 tst_resm(TINFO, "child 2 starting");
plars865695b2001-08-27 22:15:12 +0000213 if (fcntl(file_fd, F_SETLK, &lock2) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000214 err = errno;
215 tst_resm(TINFO, "child 2 lock err %d", err);
mridgedb639212005-01-04 21:04:11 +0000216 parent_free(err);
plars865695b2001-08-27 22:15:12 +0000217 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000218 tst_resm(TINFO, "child 2 pid %d locked", getpid());
plars865695b2001-08-27 22:15:12 +0000219 parent_free(0);
220 }
221
222 child_wait(child_pipe2[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000223 tst_resm(TINFO, "child 2 resuming");
plars865695b2001-08-27 22:15:12 +0000224 if (fcntl(file_fd, F_SETLKW, &lock4) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000225 err = errno;
226 tst_resm(TINFO, "child 2 lockw err %d", err);
mridgedb639212005-01-04 21:04:11 +0000227 parent_free(err);
plars865695b2001-08-27 22:15:12 +0000228 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000229 tst_resm(TINFO, "child 2 lockw locked");
plars865695b2001-08-27 22:15:12 +0000230 parent_free(0);
231 }
232
233 child_wait(child_pipe2[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000234 tst_resm(TINFO, "child 2 exiting");
plars865695b2001-08-27 22:15:12 +0000235 exit(1);
236}
237
Mike Frysingerc57fba52014-04-09 18:56:30 -0400238void do_child3(void)
plars865695b2001-08-27 22:15:12 +0000239{
subrata_modak56207ce2009-03-23 13:35:39 +0000240 int err;
mridgedb639212005-01-04 21:04:11 +0000241
plars865695b2001-08-27 22:15:12 +0000242 close(parent_pipe[0]);
243 close(child_pipe1[0]);
244 close(child_pipe1[1]);
245 close(child_pipe2[0]);
246 close(child_pipe2[1]);
247 close(child_pipe3[1]);
248
249 child_wait(child_pipe3[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000250 tst_resm(TINFO, "child 3 starting");
plars865695b2001-08-27 22:15:12 +0000251 if (fcntl(file_fd, F_SETLK, &lock3) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000252 err = errno;
253 tst_resm(TINFO, "child 3 lock err %d", err);
mridgedb639212005-01-04 21:04:11 +0000254 parent_free(err);
plars865695b2001-08-27 22:15:12 +0000255 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000256 tst_resm(TINFO, "child 3 pid %d locked", getpid());
plars865695b2001-08-27 22:15:12 +0000257 parent_free(0);
258 }
259
260 child_wait(child_pipe3[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000261 tst_resm(TINFO, "child 3 resuming");
plars865695b2001-08-27 22:15:12 +0000262 if (fcntl(file_fd, F_SETLKW, &lock5) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000263 err = errno;
264 tst_resm(TINFO, "child 3 lockw err %d", err);
mridgedb639212005-01-04 21:04:11 +0000265 parent_free(err);
plars865695b2001-08-27 22:15:12 +0000266 } else {
subrata_modak56207ce2009-03-23 13:35:39 +0000267 tst_resm(TINFO, "child 3 lockw locked");
plars865695b2001-08-27 22:15:12 +0000268 parent_free(0);
269 }
270
271 child_wait(child_pipe3[0]);
subrata_modak56207ce2009-03-23 13:35:39 +0000272 tst_resm(TINFO, "child 3 exiting");
plars865695b2001-08-27 22:15:12 +0000273 exit(1);
274}
275
subrata_modak56207ce2009-03-23 13:35:39 +0000276int do_test(struct flock *lock, pid_t pid)
plars865695b2001-08-27 22:15:12 +0000277{
278 struct flock fl;
279
mridgedb639212005-01-04 21:04:11 +0000280 fl.l_type = /* lock->l_type */ F_RDLCK;
plars865695b2001-08-27 22:15:12 +0000281 fl.l_whence = lock->l_whence;
282 fl.l_start = lock->l_start;
283 fl.l_len = lock->l_len;
subrata_modak56207ce2009-03-23 13:35:39 +0000284 fl.l_pid = (short)0;
plars865695b2001-08-27 22:15:12 +0000285 if (fcntl(file_fd, F_GETLK, &fl) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000286 tst_resm(TFAIL, "fcntl on file failed, errno =%d", errno);
subrata_modak134e8962009-02-26 11:46:54 +0000287 return 1;
plars865695b2001-08-27 22:15:12 +0000288 }
289
290 if (fl.l_type != lock->l_type) {
291 tst_resm(TFAIL, "lock type is wrong should be %s is %s",
292 str_type(lock->l_type), str_type(fl.l_type));
subrata_modak134e8962009-02-26 11:46:54 +0000293 return 1;
plars865695b2001-08-27 22:15:12 +0000294 }
295
296 if (fl.l_whence != lock->l_whence) {
297 tst_resm(TFAIL, "lock whence is wrong should be %d is %d",
298 lock->l_whence, fl.l_whence);
subrata_modak134e8962009-02-26 11:46:54 +0000299 return 1;
plars865695b2001-08-27 22:15:12 +0000300 }
301
302 if (fl.l_start != lock->l_start) {
303 tst_resm(TFAIL, "region starts in wrong place, "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800304 "should be %" PRId64 " is %" PRId64,
305 (int64_t) lock->l_start, (int64_t) fl.l_start);
subrata_modak134e8962009-02-26 11:46:54 +0000306 return 1;
plars865695b2001-08-27 22:15:12 +0000307 }
308
309 if (fl.l_len != lock->l_len) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 tst_resm(TFAIL,
311 "region length is wrong, should be %" PRId64 " is %"
312 PRId64, (int64_t) lock->l_len, (int64_t) fl.l_len);
subrata_modak134e8962009-02-26 11:46:54 +0000313 return 1;
plars865695b2001-08-27 22:15:12 +0000314 }
315
316 if (fl.l_pid != pid) {
317 tst_resm(TFAIL, "locking pid is wrong, should be %d is %d",
318 pid, fl.l_pid);
subrata_modak134e8962009-02-26 11:46:54 +0000319 return 1;
plars865695b2001-08-27 22:15:12 +0000320 }
subrata_modak43337a32009-02-26 11:43:51 +0000321 return 0;
plars865695b2001-08-27 22:15:12 +0000322}
323
subrata_modak56207ce2009-03-23 13:35:39 +0000324char *str_type(int type)
plars865695b2001-08-27 22:15:12 +0000325{
326 static char buf[20];
327
328 switch (type) {
mridgedb639212005-01-04 21:04:11 +0000329 case F_RDLCK:
subrata_modak56207ce2009-03-23 13:35:39 +0000330 return ("F_RDLCK");
mridgedb639212005-01-04 21:04:11 +0000331 case F_WRLCK:
subrata_modak56207ce2009-03-23 13:35:39 +0000332 return ("F_WRLCK");
mridgedb639212005-01-04 21:04:11 +0000333 case F_UNLCK:
subrata_modak56207ce2009-03-23 13:35:39 +0000334 return ("F_UNLCK");
plars865695b2001-08-27 22:15:12 +0000335 default:
336 sprintf(buf, "BAD VALUE: %d", type);
subrata_modak56207ce2009-03-23 13:35:39 +0000337 return (buf);
plars865695b2001-08-27 22:15:12 +0000338 }
339}
340
subrata_modak56207ce2009-03-23 13:35:39 +0000341void parent_free(int arg)
plars865695b2001-08-27 22:15:12 +0000342{
343 if (write(parent_pipe[1], &arg, sizeof(arg)) != sizeof(arg)) {
344 tst_resm(TFAIL, "couldn't send message to parent");
345 exit(1);
346 }
347}
348
Mike Frysingerc57fba52014-04-09 18:56:30 -0400349int parent_wait(void)
plars865695b2001-08-27 22:15:12 +0000350{
351 int arg;
352
353 if (read(parent_pipe[0], &arg, sizeof(arg)) != sizeof(arg)) {
354 tst_resm(TFAIL, "parent_wait() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000355 return (errno);
plars865695b2001-08-27 22:15:12 +0000356 }
subrata_modak56207ce2009-03-23 13:35:39 +0000357 return (arg);
plars865695b2001-08-27 22:15:12 +0000358}
359
subrata_modak56207ce2009-03-23 13:35:39 +0000360void child_free(int fd, int arg)
plars865695b2001-08-27 22:15:12 +0000361{
362 if (write(fd, &arg, sizeof(arg)) != sizeof(arg)) {
363 tst_resm(TFAIL, "couldn't send message to child");
364 exit(1);
365 }
366}
367
subrata_modak56207ce2009-03-23 13:35:39 +0000368void child_wait(int fd)
plars865695b2001-08-27 22:15:12 +0000369{
370 int arg;
371
372 if (read(fd, &arg, sizeof(arg)) != sizeof(arg)) {
373 tst_resm(TFAIL, "couldn't get message from parent");
374 exit(1);
375 } else if (arg == (short)STOP) {
376 exit(0);
377 }
378}
379
Mike Frysingerc57fba52014-04-09 18:56:30 -0400380void stop_children(void)
plars865695b2001-08-27 22:15:12 +0000381{
382 int arg;
383
Mike Frysingere61ddba2014-04-09 23:24:32 -0400384 signal(SIGCLD, SIG_DFL);
plars865695b2001-08-27 22:15:12 +0000385 arg = STOP;
386 child_free(child_pipe1[1], arg);
387 child_free(child_pipe2[1], arg);
388 child_free(child_pipe3[1], arg);
389 wait(0);
390}
391
Mike Frysingerc57fba52014-04-09 18:56:30 -0400392void catch_child(void)
plars865695b2001-08-27 22:15:12 +0000393{
394 tst_resm(TFAIL, "Unexpected death of child process");
395 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800396}
plars865695b2001-08-27 22:15:12 +0000397
Mike Frysingerc57fba52014-04-09 18:56:30 -0400398void catch_alarm(void)
plars865695b2001-08-27 22:15:12 +0000399{
subrata_modak56207ce2009-03-23 13:35:39 +0000400 sighold(SIGCHLD);
plars865695b2001-08-27 22:15:12 +0000401 /*
402 * Timer has runout and the children have not detected the deadlock.
403 * Need to kill the kids and exit
404 */
subrata_modak56207ce2009-03-23 13:35:39 +0000405 if (child_pid1 != 0 && (kill(child_pid1, SIGKILL)) < 0) {
plars865695b2001-08-27 22:15:12 +0000406 tst_resm(TFAIL, "Attempt to signal child 1 failed.");
407 }
408
subrata_modak56207ce2009-03-23 13:35:39 +0000409 if (child_pid2 != 0 && (kill(child_pid2, SIGKILL)) < 0) {
plars865695b2001-08-27 22:15:12 +0000410 tst_resm(TFAIL, "Attempt to signal child 2 failed.");
411 }
subrata_modak56207ce2009-03-23 13:35:39 +0000412 if (child_pid3 != 0 && (kill(child_pid3, SIGKILL)) < 0) {
mridgedb639212005-01-04 21:04:11 +0000413 tst_resm(TFAIL, "Attempt to signal child 2 failed.");
414 }
subrata_modak56207ce2009-03-23 13:35:39 +0000415 tst_resm(TFAIL, "Alarm expired, deadlock not detected");
416 tst_resm(TWARN, "You may need to kill child processes by hand");
plars865695b2001-08-27 22:15:12 +0000417 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418}
robbiew5aab8a72003-03-26 18:05:30 +0000419
420int main(int ac, char **av)
421{
422 int ans;
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200423 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200424 const char *msg;
robbiew5aab8a72003-03-26 18:05:30 +0000425 int fail = 0;
426
Garrett Cooper45e285d2010-11-22 12:19:25 -0800427 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
Garrett Cooper60fa8012010-11-22 13:50:58 -0800428 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiew5aab8a72003-03-26 18:05:30 +0000429 }
robbiewd34d5812005-07-11 22:28:09 +0000430#ifdef UCLINUX
431 maybe_run_child(&do_child1, "nddddddddd", 1, &file_fd,
432 &parent_pipe[0], &parent_pipe[1],
433 &child_pipe1[0], &child_pipe1[1],
434 &child_pipe2[0], &child_pipe2[1],
435 &child_pipe3[0], &child_pipe3[1]);
436 maybe_run_child(&do_child2, "nddddddddd", 2, &file_fd,
437 &parent_pipe[0], &parent_pipe[1],
438 &child_pipe1[0], &child_pipe1[1],
439 &child_pipe2[0], &child_pipe2[1],
440 &child_pipe3[0], &child_pipe3[1]);
441 maybe_run_child(&do_child3, "nddddddddd", 3, &file_fd,
442 &parent_pipe[0], &parent_pipe[1],
443 &child_pipe1[0], &child_pipe1[1],
444 &child_pipe2[0], &child_pipe2[1],
445 &child_pipe3[0], &child_pipe3[1]);
446#endif
447
subrata_modak56207ce2009-03-23 13:35:39 +0000448 if (setup()) { /* global testup */
robbiew5aab8a72003-03-26 18:05:30 +0000449 tst_resm(TINFO, "setup failed");
450 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800451 }
robbiew5aab8a72003-03-26 18:05:30 +0000452
453 /* check for looping state if -i option is given */
454 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800455 /* reset tst_count in case we are looping */
456 tst_count = 0;
robbiew5aab8a72003-03-26 18:05:30 +0000457
458 tst_resm(TINFO, "Enter preparation phase");
robbiewd34d5812005-07-11 22:28:09 +0000459 if ((child_pid1 = FORK_OR_VFORK()) == 0) { /* first child */
460#ifdef UCLINUX
461 if (self_exec(av[0], "nddddddddd", 1, file_fd,
462 parent_pipe[0], parent_pipe[1],
463 child_pipe1[0], child_pipe1[1],
464 child_pipe2[0], child_pipe2[1],
465 child_pipe3[0], child_pipe3[1]) < 0) {
466 perror("self_exec failed, child 1");
467 cleanup();
468 }
469#else
robbiew5aab8a72003-03-26 18:05:30 +0000470 do_child1();
robbiewd34d5812005-07-11 22:28:09 +0000471#endif
robbiew5aab8a72003-03-26 18:05:30 +0000472 } else if (child_pid1 < 0) {
473 perror("Fork failed: child 1");
474 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800475 }
robbiew5aab8a72003-03-26 18:05:30 +0000476
477 /* parent */
478
479 if ((child_pid2 = fork()) == 0) { /* second child */
robbiewd34d5812005-07-11 22:28:09 +0000480#ifdef UCLINUX
481 if (self_exec(av[0], "nddddddddd", 2, file_fd,
482 parent_pipe[0], parent_pipe[1],
483 child_pipe1[0], child_pipe1[1],
484 child_pipe2[0], child_pipe2[1],
485 child_pipe3[0], child_pipe3[1]) < 0) {
486 perror("self_exec failed, child 2");
487 cleanup();
488 }
489#else
robbiew5aab8a72003-03-26 18:05:30 +0000490 do_child2();
robbiewd34d5812005-07-11 22:28:09 +0000491#endif
robbiew5aab8a72003-03-26 18:05:30 +0000492 } else if (child_pid2 < 0) {
493 perror("Fork failed: child 2");
494 if ((kill(child_pid1, SIGKILL)) < 0) {
495 tst_resm(TFAIL, "Attempt to signal child "
496 "1 failed");
497 }
498 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800499 }
robbiew5aab8a72003-03-26 18:05:30 +0000500
501 /* parent */
502
503 if ((child_pid3 = fork()) == 0) { /* third child */
robbiewd34d5812005-07-11 22:28:09 +0000504#ifdef UCLINUX
505 if (self_exec(av[0], "nddddddddd", 3, file_fd,
506 parent_pipe[0], parent_pipe[1],
507 child_pipe1[0], child_pipe1[1],
508 child_pipe2[0], child_pipe2[1],
509 child_pipe3[0], child_pipe3[1]) < 0) {
510 perror("self_exec failed, child 3");
511 cleanup();
512 }
513#else
514 do_child3();
515#endif
robbiew5aab8a72003-03-26 18:05:30 +0000516 do_child3();
517 } else if (child_pid3 < 0) {
518 perror("Fork failed: child 3");
519 if ((kill(child_pid1, SIGKILL)) < 0) {
520 tst_resm(TFAIL, "Attempt to signal child "
521 "1 failed");
522 }
523 if ((kill(child_pid2, SIGKILL)) < 0) {
524 tst_resm(TFAIL, "Attempt to signal child 2 "
525 "failed");
526 }
527 cleanup();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800528 }
robbiew5aab8a72003-03-26 18:05:30 +0000529 /* parent */
530
531 close(parent_pipe[1]);
532 close(child_pipe1[0]);
533 close(child_pipe2[0]);
534 close(child_pipe3[0]);
535 tst_resm(TINFO, "Exit preparation phase");
536
mridgedb639212005-01-04 21:04:11 +0000537/* //block1: */
robbiew5aab8a72003-03-26 18:05:30 +0000538 tst_resm(TINFO, "Enter block 1");
539 fail = 0;
540 /*
541 * child 1 puts first lock (bytes 2-7)
542 */
543 child_free(child_pipe1[1], 0);
544 if (parent_wait()) {
545 tst_resm(TFAIL, "didn't set first child's lock, "
546 "errno: %d", errno);
547 }
548 if (do_test(&lock1, child_pid1)) {
549 tst_resm(TINFO, "do_test failed child 1");
550 fail = 1;
551 }
552
553 /*
554 * child 2 puts second lock (bytes 9-14)
555 */
556 child_free(child_pipe2[1], 0);
557 if (parent_wait()) {
558 tst_resm(TINFO, "didn't set second child's lock, "
559 "errno: %d", errno);
560 fail = 1;
561 }
562 if (do_test(&lock2, child_pid2)) {
563 tst_resm(TINFO, "do_test failed child 2");
564 fail = 1;
565 }
566
567 /*
568 * child 3 puts third lock (bytes 17-22)
569 */
570 child_free(child_pipe3[1], 0);
571 if (parent_wait()) {
572 tst_resm(TFAIL, "didn't set third child's lock, "
573 "errno: %d", errno);
574 fail = 1;
575 }
576 if (do_test(&lock3, child_pid3)) {
577 tst_resm(TINFO, "do_test failed child 3");
578 fail = 1;
579 }
580
581 /*
582 * child 2 tries to lock same range as
583 * child 3's first lock.
584 */
585 child_free(child_pipe2[1], 0);
586
587 /*
588 * child 3 tries to lock same range as
589 * child 1 and child 2's first locks.
590 */
591 child_free(child_pipe3[1], 0);
592
593 /*
594 * Tell child 1 to release its lock. This should cause a
595 * delayed deadlock between child 2 and child 3.
596 */
597 child_free(child_pipe1[1], 0);
598
599 /*
600 * Setup an alarm to go off in case the deadlock is not
601 * detected
602 */
603 alarm(TIME_OUT);
604
605 /*
606 * should get a message from child 3 telling that its
607 * second lock EDEADLOCK
608 */
609 if ((ans = parent_wait()) != EDEADLK) {
610 tst_resm(TFAIL, "child 2 didn't deadlock, "
611 "returned: %d", ans);
612 fail = 1;
613 }
614
615 /*
616 * Double check that lock 2 and lock 3 are still right
617 */
618 do_test(&lock2, child_pid2);
619 do_test(&lock3, child_pid3);
620
621 stop_children();
robbiew5aab8a72003-03-26 18:05:30 +0000622 if (fail) {
623 tst_resm(TINFO, "Block 1 FAILED");
624 } else {
625 tst_resm(TINFO, "Block 1 PASSED");
626 }
627 tst_resm(TINFO, "Exit block 1");
628 }
629 waitpid(child_pid1, &child_stat, 0);
630 waitpid(child_pid2, &child_stat, 0);
631 waitpid(child_pid3, &child_stat, 0);
632 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800633 tst_exit();
Chris Dearmanec6edca2012-10-17 19:54:01 -0700634}