2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3 * Authors: Doug Rabson <dfr@rabson.org>
4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
33 #include <sys/mount.h>
48 #if __FreeBSD_version >= 800028
51 #if __FreeBSD_version < 800000 && __FreeBSD_version >= 700103
54 #if __FreeBSD_version < 700000 && __FreeBSD_version >= 603102
57 #include <sys/cdefs.h>
67 make_file(const char *pathname, off_t sz)
70 const char *template = "/flocktempXXXXXX";
75 if (stat(pathname, &st) == 0) {
76 if (S_ISREG(st.st_mode)) {
77 fd = open(pathname, O_RDWR);
79 err(1, "open(%s)", pathname);
80 if (ftruncate(fd, sz) < 0)
86 len = strlen(pathname) + strlen(template) + 1;
87 filename = malloc(len);
88 strcpy(filename, pathname);
89 strcat(filename, template);
90 fd = mkstemp(filename);
93 if (ftruncate(fd, sz) < 0)
95 if (unlink(filename) < 0)
103 ignore_alarm(int __unused sig)
108 safe_waitpid(pid_t pid)
115 while (waitpid(pid, &status, 0) != pid) {
128 printf("FAIL (%s)\n", #test); \
134 do { printf("SUCCEED\n"); return 0; } while (0)
137 * Test 1 - F_GETLK on unlocked region
139 * If no lock is found that would prevent this lock from being
140 * created, the structure is left unchanged by this function call
141 * except for the lock type which is set to F_UNLCK.
144 test1(int fd, __unused int argc, const __unused char **argv)
146 struct flock fl1, fl2;
148 memset(&fl1, 1, sizeof(fl1));
149 fl1.l_type = F_WRLCK;
150 fl1.l_whence = SEEK_SET;
153 if (fcntl(fd, F_GETLK, &fl1) < 0)
156 printf("1 - F_GETLK on unlocked region: ");
157 FAIL(fl1.l_start != fl2.l_start);
158 FAIL(fl1.l_len != fl2.l_len);
159 FAIL(fl1.l_pid != fl2.l_pid);
160 FAIL(fl1.l_type != F_UNLCK);
161 FAIL(fl1.l_whence != fl2.l_whence);
163 FAIL(fl1.l_sysid != fl2.l_sysid);
170 * Test 2 - F_SETLK on locked region
172 * If a shared or exclusive lock cannot be set, fcntl returns
173 * immediately with EACCES or EAGAIN.
176 test2(int fd, __unused int argc, const __unused char **argv)
179 * We create a child process to hold the lock which we will
180 * test. We use a pipe to communicate with the child.
194 fl.l_whence = SEEK_SET;
202 * We are the child. We set a write lock and then
203 * write one byte back to the parent to tell it. The
204 * parent will kill us when its done.
206 if (fcntl(fd, F_SETLK, &fl) < 0)
207 err(1, "F_SETLK (child)");
208 if (write(pfd[1], "a", 1) < 0)
209 err(1, "writing to pipe (child)");
215 * Wait until the child has set its lock and then perform the
218 if (read(pfd[0], &ch, 1) != 1)
219 err(1, "reading from pipe (child)");
222 * fcntl should return -1 with errno set to either EACCES or
225 printf("2 - F_SETLK on locked region: ");
226 res = fcntl(fd, F_SETLK, &fl);
232 FAIL(errno != EACCES && errno != EAGAIN);
238 * Test 3 - F_SETLKW on locked region
240 * If a shared or exclusive lock is blocked by other locks, the
241 * process waits until the request can be satisfied.
243 * XXX this test hangs on FreeBSD NFS filesystems due to limitations
244 * in FreeBSD's client (and server) lockd implementation.
247 test3(int fd, __unused int argc, const __unused char **argv)
250 * We create a child process to hold the lock which we will
251 * test. We use a pipe to communicate with the child.
265 fl.l_whence = SEEK_SET;
273 * We are the child. We set a write lock and then
274 * write one byte back to the parent to tell it. The
275 * parent will kill us when its done.
277 if (fcntl(fd, F_SETLK, &fl) < 0)
278 err(1, "F_SETLK (child)");
279 if (write(pfd[1], "a", 1) < 0)
280 err(1, "writing to pipe (child)");
286 * Wait until the child has set its lock and then perform the
289 if (read(pfd[0], &ch, 1) != 1)
290 err(1, "reading from pipe (child)");
293 * fcntl should wait until the alarm and then return -1 with
294 * errno set to EINTR.
296 printf("3 - F_SETLKW on locked region: ");
300 res = fcntl(fd, F_SETLKW, &fl);
306 FAIL(errno != EINTR);
312 * Test 4 - F_GETLK on locked region
314 * Get the first lock that blocks the lock.
317 test4(int fd, __unused int argc, const __unused char **argv)
320 * We create a child process to hold the lock which we will
321 * test. We use a pipe to communicate with the child.
334 fl.l_whence = SEEK_SET;
342 * We are the child. We set a write lock and then
343 * write one byte back to the parent to tell it. The
344 * parent will kill us when its done.
346 if (fcntl(fd, F_SETLK, &fl) < 0)
347 err(1, "F_SETLK (child)");
348 if (write(pfd[1], "a", 1) < 0)
349 err(1, "writing to pipe (child)");
355 * Wait until the child has set its lock and then perform the
358 if (read(pfd[0], &ch, 1) != 1)
359 err(1, "reading from pipe (child)");
362 * fcntl should return a lock structure reflecting the lock we
363 * made in the child process.
365 if (fcntl(fd, F_GETLK, &fl) < 0)
368 printf("4 - F_GETLK on locked region: ");
369 FAIL(fl.l_start != 0);
370 FAIL(fl.l_len != 99);
371 FAIL(fl.l_type != F_WRLCK);
372 FAIL(fl.l_pid != pid);
374 FAIL(fl.l_sysid != 0);
386 * Test 5 - F_SETLKW simple deadlock
388 * If a blocking shared lock request would cause a deadlock (i.e. the
389 * lock request is blocked by a process which is itself blocked on a
390 * lock currently owned by the process making the new request),
391 * EDEADLK is returned.
394 test5(int fd, __unused int argc, const __unused char **argv)
397 * We create a child process to hold the lock which we will
398 * test. Because our test relies on the child process being
399 * blocked on the parent's lock, we can't easily use a pipe to
400 * synchronize so we just sleep in the parent to given the
401 * child a chance to setup.
403 * To create the deadlock condition, we arrange for the parent
404 * to lock the first byte of the file and the child to lock
405 * the second byte. After locking the second byte, the child
406 * will attempt to lock the first byte of the file, and
407 * block. The parent will then attempt to lock the second byte
408 * (owned by the child) which should cause deadlock.
415 * Lock the first byte in the parent.
420 fl.l_whence = SEEK_SET;
421 if (fcntl(fd, F_SETLK, &fl) < 0)
422 err(1, "F_SETLK 1 (parent)");
430 * Lock the second byte in the child and then block on
434 if (fcntl(fd, F_SETLK, &fl) < 0)
435 err(1, "F_SETLK (child)");
437 if (fcntl(fd, F_SETLKW, &fl) < 0)
438 err(1, "F_SETLKW (child)");
443 * Wait until the child has set its lock and then perform the
449 * fcntl should immediately return -1 with errno set to
450 * EDEADLK. If the alarm fires, we failed to detect the
454 printf("5 - F_SETLKW simple deadlock: ");
457 res = fcntl(fd, F_SETLKW, &fl);
462 FAIL(errno != EDEADLK);
467 if (fcntl(fd, F_SETLK, &fl) < 0)
471 * Cancel the alarm to avoid confusing later tests.
479 * Test 6 - F_SETLKW complex deadlock.
481 * This test involves three process, P, C1 and C2. We set things up so
482 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We
483 * also block C2 by attempting to lock byte zero. Lastly, P attempts
484 * to lock a range including byte 1 and 2. This represents a deadlock
485 * (due to C2's blocking attempt to lock byte zero).
488 test6(int fd, __unused int argc, const __unused char **argv)
491 * Because our test relies on the child process being blocked
492 * on the parent's lock, we can't easily use a pipe to
493 * synchronize so we just sleep in the parent to given the
494 * children a chance to setup.
501 * Lock the first byte in the parent.
506 fl.l_whence = SEEK_SET;
507 if (fcntl(fd, F_SETLK, &fl) < 0)
508 err(1, "F_SETLK 1 (parent)");
517 * Lock the second byte in the child and then sleep
520 if (fcntl(fd, F_SETLK, &fl) < 0)
521 err(1, "F_SETLK (child1)");
533 * Lock the third byte in the child and then block on
537 if (fcntl(fd, F_SETLK, &fl) < 0)
538 err(1, "F_SETLK (child2)");
540 if (fcntl(fd, F_SETLKW, &fl) < 0)
541 err(1, "F_SETLKW (child2)");
546 * Wait until the children have set their locks and then
552 * fcntl should immediately return -1 with errno set to
553 * EDEADLK. If the alarm fires, we failed to detect the
557 printf("6 - F_SETLKW complex deadlock: ");
561 res = fcntl(fd, F_SETLKW, &fl);
570 if (fcntl(fd, F_SETLK, &fl) < 0)
574 FAIL(errno != EDEADLK);
577 * Cancel the alarm to avoid confusing later tests.
585 * Test 7 - F_SETLK shared lock on exclusive locked region
587 * If a shared or exclusive lock cannot be set, fcntl returns
588 * immediately with EACCES or EAGAIN.
591 test7(int fd, __unused int argc, const __unused char **argv)
594 * We create a child process to hold the lock which we will
595 * test. We use a pipe to communicate with the child.
609 fl.l_whence = SEEK_SET;
617 * We are the child. We set a write lock and then
618 * write one byte back to the parent to tell it. The
619 * parent will kill us when its done.
621 if (fcntl(fd, F_SETLK, &fl) < 0)
622 err(1, "F_SETLK (child)");
623 if (write(pfd[1], "a", 1) < 0)
624 err(1, "writing to pipe (child)");
630 * Wait until the child has set its lock and then perform the
633 if (read(pfd[0], &ch, 1) != 1)
634 err(1, "reading from pipe (child)");
637 * fcntl should wait until the alarm and then return -1 with
638 * errno set to EINTR.
640 printf("7 - F_SETLK shared lock on exclusive locked region: ");
643 res = fcntl(fd, F_SETLK, &fl);
650 FAIL(errno != EACCES && errno != EAGAIN);
656 * Test 8 - F_SETLK shared lock on share locked region
658 * When a shared lock is set on a segment of a file, other processes
659 * shall be able to set shared locks on that segment or a portion of
663 test8(int fd, __unused int argc, const __unused char **argv)
666 * We create a child process to hold the lock which we will
667 * test. We use a pipe to communicate with the child.
681 fl.l_whence = SEEK_SET;
689 * We are the child. We set a write lock and then
690 * write one byte back to the parent to tell it. The
691 * parent will kill us when its done.
693 if (fcntl(fd, F_SETLK, &fl) < 0)
694 err(1, "F_SETLK (child)");
695 if (write(pfd[1], "a", 1) < 0)
696 err(1, "writing to pipe (child)");
702 * Wait until the child has set its lock and then perform the
705 if (read(pfd[0], &ch, 1) != 1)
706 err(1, "reading from pipe (child)");
709 * fcntl should wait until the alarm and then return -1 with
710 * errno set to EINTR.
712 printf("8 - F_SETLK shared lock on share locked region: ");
715 res = fcntl(fd, F_SETLK, &fl);
725 if (fcntl(fd, F_SETLK, &fl) < 0)
734 * Test 9 - F_SETLK exclusive lock on share locked region
736 * If a shared or exclusive lock cannot be set, fcntl returns
737 * immediately with EACCES or EAGAIN.
740 test9(int fd, __unused int argc, const __unused char **argv)
743 * We create a child process to hold the lock which we will
744 * test. We use a pipe to communicate with the child.
758 fl.l_whence = SEEK_SET;
766 * We are the child. We set a write lock and then
767 * write one byte back to the parent to tell it. The
768 * parent will kill us when its done.
770 if (fcntl(fd, F_SETLK, &fl) < 0)
771 err(1, "F_SETLK (child)");
772 if (write(pfd[1], "a", 1) < 0)
773 err(1, "writing to pipe (child)");
779 * Wait until the child has set its lock and then perform the
782 if (read(pfd[0], &ch, 1) != 1)
783 err(1, "reading from pipe (child)");
786 * fcntl should wait until the alarm and then return -1 with
787 * errno set to EINTR.
789 printf("9 - F_SETLK exclusive lock on share locked region: ");
792 res = fcntl(fd, F_SETLK, &fl);
799 FAIL(errno != EACCES && errno != EAGAIN);
805 * Test 10 - trying to set bogus pid or sysid values
807 * The l_pid and l_sysid fields are only used with F_GETLK to return
808 * the process ID of the process holding a blocking lock and the
809 * system ID of the system that owns that process
812 test10(int fd, __unused int argc, const __unused char **argv)
815 * We create a child process to hold the lock which we will
816 * test. We use a pipe to communicate with the child.
829 fl.l_whence = SEEK_SET;
841 * We are the child. We set a write lock and then
842 * write one byte back to the parent to tell it. The
843 * parent will kill us when its done.
845 if (fcntl(fd, F_SETLK, &fl) < 0)
846 err(1, "F_SETLK (child)");
847 if (write(pfd[1], "a", 1) < 0)
848 err(1, "writing to pipe (child)");
854 * Wait until the child has set its lock and then perform the
857 if (read(pfd[0], &ch, 1) != 1)
858 err(1, "reading from pipe (child)");
860 printf("10 - trying to set bogus pid or sysid values: ");
862 if (fcntl(fd, F_GETLK, &fl) < 0)
870 FAIL(fl.l_pid != pid);
872 FAIL(fl.l_sysid != 0);
879 * Test 11 - remote locks
881 * XXX temporary interface which will be removed when the kernel lockd
885 test11(int fd, __unused int argc, const __unused char **argv)
887 #ifdef F_SETLK_REMOTE
897 fl.l_whence = SEEK_SET;
901 printf("11 - remote locks: ");
903 res = fcntl(fd, F_SETLK_REMOTE, &fl);
907 res = fcntl(fd, F_SETLK_REMOTE, &fl);
909 FAIL(errno != EACCES && errno != EAGAIN);
911 res = fcntl(fd, F_GETLK, &fl);
913 FAIL(fl.l_pid != 9999);
914 FAIL(fl.l_sysid != 1001);
920 res = fcntl(fd, F_SETLK_REMOTE, &fl);
927 fl.l_whence = SEEK_SET;
929 res = fcntl(fd, F_SETLK_REMOTE, &fl);
933 res = fcntl(fd, F_SETLK_REMOTE, &fl);
936 fl.l_type = F_UNLCKSYS;
938 res = fcntl(fd, F_SETLK_REMOTE, &fl);
942 res = fcntl(fd, F_GETLK, &fl);
944 FAIL(fl.l_pid != 1234);
945 FAIL(fl.l_sysid != 1002);
947 fl.l_type = F_UNLCKSYS;
949 res = fcntl(fd, F_SETLK_REMOTE, &fl);
959 * Test 12 - F_SETLKW on locked region which is then unlocked
961 * If a shared or exclusive lock is blocked by other locks, the
962 * process waits until the request can be satisfied.
965 test12(int fd, __unused int argc, const __unused char **argv)
968 * We create a child process to hold the lock which we will
969 * test. We use a pipe to communicate with the child.
983 fl.l_whence = SEEK_SET;
991 * We are the child. We set a write lock and then
992 * write one byte back to the parent to tell it. The
993 * parent will kill us when its done.
995 if (fcntl(fd, F_SETLK, &fl) < 0)
996 err(1, "F_SETLK (child)");
997 if (write(pfd[1], "a", 1) < 0)
998 err(1, "writing to pipe (child)");
1005 * Wait until the child has set its lock and then perform the
1008 if (read(pfd[0], &ch, 1) != 1)
1009 err(1, "reading from pipe (child)");
1012 * fcntl should wait until the alarm and then return -1 with
1013 * errno set to EINTR.
1015 printf("12 - F_SETLKW on locked region which is then unlocked: ");
1019 res = fcntl(fd, F_SETLKW, &fl);
1028 fl.l_type = F_UNLCK;
1029 if (fcntl(fd, F_SETLK, &fl) < 0)
1036 * Test 13 - F_SETLKW on locked region, race with owner
1038 * If a shared or exclusive lock is blocked by other locks, the
1039 * process waits until the request can be satisfied.
1042 test13(int fd, __unused int argc, const __unused char **argv)
1045 * We create a child process to hold the lock which we will
1046 * test. We use a pipe to communicate with the child.
1054 struct itimerval itv;
1056 printf("13 - F_SETLKW on locked region, race with owner: ");
1059 for (i = 0; i < 100; i++) {
1065 fl.l_type = F_WRLCK;
1066 fl.l_whence = SEEK_SET;
1074 * We are the child. We set a write lock and then
1075 * write one byte back to the parent to tell it. The
1076 * parent will kill us when its done.
1078 if (fcntl(fd, F_SETLK, &fl) < 0)
1079 err(1, "F_SETLK (child)");
1080 if (write(pfd[1], "a", 1) < 0)
1081 err(1, "writing to pipe (child)");
1088 * Wait until the child has set its lock and then perform the
1091 while (read(pfd[0], &ch, 1) != 1) {
1094 err(1, "reading from pipe (child)");
1098 * fcntl should wait until the alarm and then return -1 with
1099 * errno set to EINTR.
1101 itv.it_interval.tv_sec = 0;
1102 itv.it_interval.tv_usec = 0;
1103 itv.it_value.tv_sec = 0;
1104 itv.it_value.tv_usec = 2;
1105 setitimer(ITIMER_REAL, &itv, NULL);
1107 res = fcntl(fd, F_SETLKW, &fl);
1112 FAIL(!(res == 0 || (res == -1 && errno == EINTR)));
1116 fl.l_type = F_UNLCK;
1117 if (fcntl(fd, F_SETLK, &fl) < 0)
1124 * Test 14 - soak test
1127 test14(int fd, int argc, const char **argv)
1129 #define CHILD_COUNT 20
1131 * We create a set of child processes and let each one run
1132 * through a random sequence of locks and unlocks.
1134 int i, j, id, id_base;
1135 int pids[CHILD_COUNT], pid;
1141 struct itimerval itv;
1146 id_base = strtol(argv[1], NULL, 0);
1148 printf("14 - soak test: ");
1151 for (i = 0; i < 128; i++)
1154 for (i = 0; i < CHILD_COUNT; i++) {
1161 * Parent - record the pid and continue.
1168 * Child - do some work and exit.
1173 for (j = 0; j < 50; j++) {
1174 int start, end, len;
1178 start = random() & 127;
1179 end = random() & 127;
1180 } while (end <= start);
1183 wrlock = random() & 1;
1188 fl.l_whence = SEEK_SET;
1190 fl.l_type = wrlock ? F_WRLCK : F_RDLCK;
1192 fl.l_type = F_UNLCK;
1194 itv.it_interval.tv_sec = 0;
1195 itv.it_interval.tv_usec = 0;
1196 itv.it_value.tv_sec = 0;
1197 itv.it_value.tv_usec = 3000;
1198 setitimer(ITIMER_REAL, &itv, NULL);
1200 if (fcntl(fd, F_SETLKW, &fl) < 0) {
1201 if (errno == EDEADLK || errno == EINTR) {
1203 snprintf(outbuf, sizeof(outbuf),
1204 "%d[%d]: %s [%d .. %d] %s\n",
1206 set ? (wrlock ? "write lock"
1208 : "unlock", start, end,
1221 itv.it_interval.tv_sec = 0;
1222 itv.it_interval.tv_usec = 0;
1223 itv.it_value.tv_sec = 0;
1224 itv.it_value.tv_usec = 0;
1225 setitimer(ITIMER_REAL, &itv, NULL);
1228 snprintf(outbuf, sizeof(outbuf),
1229 "%d[%d]: %s [%d .. %d] succeeded\n",
1231 set ? (wrlock ? "write lock" : "read lock")
1232 : "unlock", start, end);
1233 write(1, outbuf, strlen(outbuf));
1239 * We got a write lock - write
1240 * our ID to each byte that we
1243 for (i = start; i < end; i++)
1245 memset(&buf[start], id, len);
1246 if (pwrite(fd, &buf[start], len,
1248 printf("%d: short write\n", id);
1253 * We got a read lock - read
1254 * the bytes which we claimed
1255 * so that we can check that
1259 for (i = start; i < end; i++)
1261 if (pread(fd, &buf[start], len,
1263 printf("%d: short read\n", id);
1268 for (i = start; i < end; i++)
1275 * Read back the whole region so that we can
1276 * check that all the bytes we have some kind
1277 * of claim to have the correct value.
1279 if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) {
1280 printf("%d: short read\n", id);
1284 for (i = 0; i < 128; i++) {
1285 if (map[i] != F_UNLCK && buf[i] != tbuf[i]) {
1286 snprintf(outbuf, sizeof(outbuf),
1287 "%d: byte %d expected %d, "
1288 "got %d\n", id, i, buf[i], tbuf[i]);
1289 write(1, outbuf, strlen(outbuf));
1295 printf("%d[%d]: done\n", id, j);
1301 for (i = 0; i < CHILD_COUNT; i++) {
1302 status += safe_waitpid(pids[i]);
1311 * Test 15 - flock(2) semantcs
1313 * When a lock holder has a shared lock and attempts to upgrade that
1314 * shared lock to exclusive, it must drop the shared lock before
1315 * blocking on the exclusive lock.
1317 * To test this, we first arrange for two shared locks on the file,
1318 * and then attempt to upgrade one of them to exclusive. This should
1319 * drop one of the shared locks and block. We interrupt the blocking
1320 * lock request and examine the lock state of the file after dropping
1321 * the other shared lock - there should be no active locks at this
1325 test15(int fd, __unused int argc, const __unused char **argv)
1329 * We create a child process to hold the lock which we will
1330 * test. We use a pipe to communicate with the child.
1332 * Since we only have one file descriptors and lock ownership
1333 * for flock(2) goes with the file descriptor, we use fcntl to
1334 * set the child's shared lock.
1352 * We are the child. We set a shared lock and then
1353 * write one byte back to the parent to tell it. The
1354 * parent will kill us when its done.
1358 fl.l_type = F_RDLCK;
1359 fl.l_whence = SEEK_SET;
1360 if (fcntl(fd, F_SETLK, &fl) < 0)
1361 err(1, "fcntl(F_SETLK) (child)");
1362 if (write(pfd[1], "a", 1) < 0)
1363 err(1, "writing to pipe (child)");
1369 * Wait until the child has set its lock and then perform the
1372 if (read(pfd[0], &ch, 1) != 1)
1373 err(1, "reading from pipe (child)");
1376 if (flock(fd, LOCK_SH) < 0)
1377 err(1, "flock shared");
1380 * flock should wait until the alarm and then return -1 with
1381 * errno set to EINTR.
1383 printf("15 - flock(2) semantics: ");
1389 * Kill the child to force it to drop its locks.
1396 fl.l_type = F_WRLCK;
1397 fl.l_whence = SEEK_SET;
1398 res = fcntl(fd, F_GETLK, &fl);
1403 FAIL(fl.l_type != F_UNLCK);
1412 int (*testfn)(int, int, const char **); /* function to perform the test */
1413 int num; /* test number */
1414 int intr; /* non-zero if the test interrupts a lock */
1417 struct test tests[] = {
1434 int test_count = sizeof(tests) / sizeof(tests[0]);
1437 main(int argc, const char *argv[])
1443 struct sigaction sa;
1445 const char **test_argv;
1448 errx(1, "usage: flock <directory> [test number] ...");
1451 fd = make_file(argv[1], 1024);
1453 testnum = strtol(argv[2], NULL, 0);
1454 test_argc = argc - 2;
1455 test_argv = argv + 2;
1462 sa.sa_handler = ignore_alarm;
1463 sigemptyset(&sa.sa_mask);
1465 sigaction(SIGALRM, &sa, 0);
1468 #if defined(__FreeBSD__) && __FreeBSD_version < 700110
1471 * FreeBSD with userland NLM can't interrupt a blocked
1472 * lock request on an NFS mounted filesystem.
1476 nointr = !strcmp(st.f_fstypename, "nfs");
1480 for (i = 0; i < test_count; i++) {
1481 if (tests[i].intr && nointr)
1483 if (!testnum || tests[i].num == testnum)
1484 tests[i].testfn(fd, test_argc, test_argv);