1 /*
2 *
3 * Copyright (c) 2003 The Regents of the University of California. All
4 * rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 /*
33 *
34 * openrace.c: A test program as part of FUSD.
35 *
36 * This regression test program tries to exercise the FUSD race
37 * condition between a device provider closing (and unregistering a
38 * device), and clients trying to open that device.
39 *
40 * It should run for less than 30 seconds, then exit, saying ALL TESTS
41 * PASSED. If it freezes, or processes get stuck in the D state, or
42 * you end up with zombie devices (in /dev/fusd/status), then there is
43 * a problem.
44 *
45 * $Id: openrace2.c,v 1.4 2004-04-28 18:40:07 girod Exp $
46 */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <fcntl.h>
52 #include <errno.h>
53 #include <sys/wait.h>
54 #include <signal.h>
55 #include <string.h>
56
57 #include "fusd.h"
58
59 #define DEVNAME "/dev/testfusd/openrace"
60
61
62 #define FORK \
63 tmp = fork(); \
64 if (tmp < 0) { perror("can't fork"); exit(1); } \
65 if (tmp == 0)
66
67 #define ITERATIONS 1000
68 #define MAX_BEFORE_EXIT ((n/2) * ITERATIONS)
69
70 int n;
71
72 void done(int signo)
73 {
74 static int num_done = 0;
75 int status;
76 pid_t pid;
77
78 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
79 printf("pid [%d] done\n", pid);
80 num_done++;
81 }
82
83 /* if all N clients, plus the server, are done... we're done */
84 if (num_done == n+1) {
85 printf("test complete\n");
86 exit(0);
87 }
88 }
89
90 int _open(struct fusd_file_info *file)
91 {
92 static int count = 0;
93
94 /* exit abruptly in the middle of the request stream */
95 if (count++ >= MAX_BEFORE_EXIT)
96 exit(1);
97
98 return -ENOMEM;
99 }
100
101 int _close(struct fusd_file_info *file)
102 {
103 return 0;
104 }
105
106
107 int main(int argc, char *argv[])
108 {
109 int tmp, i;
110
111 if (argc != 2 || (n = atoi(argv[1])) <= 0) {
112 fprintf(stderr, "usage: %s <number-of-clients> (use at least 10 or 20)\n", argv[0]);
113 exit(0);
114 }
115
116 printf("master is pid %d\n", getpid());
117 signal(SIGCHLD, done);
118
119 /* fork server */
120 FORK {
121 fusd_file_operations_t
122 fops = {
123 open: _open,
124 close: _close
125 };
126
127 if (fusd_register(DEVNAME, 0666, 0, &fops) < 0) {
128 perror("Register failed");
129 exit(1);
130 }
131 printf("server is pid %d, will respond to %d before exiting\n",
132 getpid(), MAX_BEFORE_EXIT);
133 fusd_run();
134 }
135
136 sleep(1);
137
138 for (i = 0; i < n; i++) {
139 FORK {
140 int j;
141 int enomem=0, enoent=0, epipe=0, eother=0;
142
143 printf("launched client %d, pid %d\n", i, getpid());
144
145 for (j = 0; j < ITERATIONS; j++) {
146 open(DEVNAME, O_RDWR);
147
148 switch (errno) {
149 case ENOMEM:
150 enomem++;
151 break;
152 case ENOENT:
153 enoent++;
154 break;
155 case EPIPE:
156 epipe++;
157 break;
158 default:
159 eother++;
160 printf("[%d] got strange retval %d (%m)\n", getpid(), errno);
161 break;
162 }
163 }
164
165 printf("[%d] done; %d nomem, %d noent, %d pipe, %d other\n", getpid(),
166 enomem, enoent, epipe, eother);
167 exit(0);
168 }
169 }
170
171 /* parent: wait for children to all exit */
172 while (1)
173 pause();
174 }
175
176
177
178
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.