1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/* Stress test for watch code: two processes communicating by watches */
#include "xs.h"
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc __attribute__((unused)), char *argv[])
{
int childpid, status, fds[2];
bool parent;
unsigned int i, acks = 0;
struct xs_handle *h;
char *data;
unsigned int len;
const char *path, *otherpath;
pipe(fds);
childpid = fork();
if (childpid == -1)
barf_perror("Failed fork");
parent = (childpid != 0);
h = xs_daemon_open();
if (!h)
barf_perror("Could not connect to daemon");
if (!xs_watch(h, "/", "token", 0))
barf_perror("Could not set watch");
if (parent) {
char c;
if (read(fds[0], &c, 1) != 1)
barf("Child exited");
path = "/parent";
otherpath = "/child";
/* Create initial node. */
if (!xs_write(h, path, "0", 2, O_CREAT))
barf_perror("Write to %s failed", path);
} else {
path = "/child";
otherpath = "/parent";
if (write(fds[1], "", 1) != 1)
barf_perror("Write to parent failed");
}
for (i = 0; i < (argv[1] ? (unsigned)atoi(argv[1]) : 100);) {
char **vec;
vec = xs_read_watch(h);
if (!vec)
barf_perror("Read watch failed");
if (!streq(vec[1], "token"))
barf("Watch token %s bad", vec[1]);
if (streq(vec[0], otherpath)) {
char number[32];
data = xs_read(h, otherpath, &len);
if (!data)
barf_perror("reading %s", otherpath);
sprintf(number, "%i", atoi(data) + 1);
free(data);
if (!xs_write(h, path, number, strlen(number) + 1,
O_CREAT))
barf_perror("writing %s", path);
i++;
} else if (!streq(vec[0], path))
barf_perror("Watch fired on unknown path %s", vec[0]);
xs_acknowledge_watch(h, vec[1]);
acks++;
free(vec);
}
if (!parent) {
while (acks != 2 * i - 1) {
char **vec;
vec = xs_read_watch(h);
if (!vec)
barf_perror("Watch failed");
if (!streq(vec[0], path))
barf_perror("Watch fired path %s", vec[0]);
if (!streq(vec[1], "token"))
barf("Watch token %s bad", vec[1]);
free(vec);
printf("Expect %i events, only got %i\n",
2 * i - 1, acks);
acks++;
}
exit(0);
}
if (acks != 2 * i)
barf("Parent got %i watch events\n", acks);
printf("Waiting for %i\n", childpid);
if (waitpid(childpid, &status, 0) != childpid)
barf_perror("Child wait failed");
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
barf_perror("Child status %i", status);
data = xs_read(h, path, &len);
if (atoi(data) != 2 * (int)i)
barf("%s count is %s\n", path, data);
free(data);
data = xs_read(h, otherpath, &len);
if (atoi(data) != 2 * (int)i - 1)
barf("%s count is %s\n", otherpath, data);
free(data);
printf("Success!\n");
exit(0);
}
|