[package] hotplug2: Fix event blocking when there are no available children (#6958...
[openwrt/svn-archive/archive.git] / package / hotplug2 / patches / 160-event_block_fix.patch
1 diff -x '*~' -ur hotplug2-201/uevent.c hotplug2-201.patched/uevent.c
2 --- hotplug2-201/uevent.c 2009-12-09 20:44:14.000000000 +0200
3 +++ hotplug2-201.patched/uevent.c 2010-04-02 23:03:11.000000000 +0300
4 @@ -132,6 +132,8 @@
5
6 dest = xmalloc(sizeof(struct uevent_t));
7 dest->action = src->action;
8 + dest->seqnum = src->seqnum;
9 + dest->action_str = strdup(src->action_str);
10 dest->env_vars_c = src->env_vars_c;
11 dest->env_vars = xmalloc(sizeof(struct env_var_t) * dest->env_vars_c);
12 dest->plain_s = src->plain_s;
13 diff -x '*~' -ur hotplug2-201/workers/worker_fork.c hotplug2-201.patched/workers/worker_fork.c
14 --- hotplug2-201/workers/worker_fork.c 2010-04-03 17:02:15.000000000 +0300
15 +++ hotplug2-201.patched/workers/worker_fork.c 2010-04-03 17:04:27.000000000 +0300
16 @@ -1,6 +1,69 @@
17 #include "worker_fork.h"
18
19 static struct worker_fork_ctx_t *global_ctx;
20 +static struct worker_fork_uevent_t *uevent_list;
21 +
22 +static void worker_fork_uevent_free(struct worker_fork_uevent_t *node) {
23 + uevent_free(node->uevent);
24 + free(node);
25 +}
26 +
27 +static void worker_fork_uevent_add(void *in_ctx, struct uevent_t *uevent) {
28 + char **env;
29 + int i;
30 + struct worker_fork_ctx_t *ctx = in_ctx;
31 + struct worker_fork_uevent_t *node, *walker;
32 +
33 + node = malloc(sizeof (struct worker_fork_uevent_t));
34 + node->uevent = uevent_dup(uevent);
35 + node->next = NULL;
36 +
37 + if (!uevent_list) uevent_list = node;
38 + else {
39 + /*
40 + * Put events that need to fork first and in reverse order
41 + */
42 + env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
43 + for (i = 0; i < node->uevent->env_vars_c; i++) {
44 + env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
45 + putenv(env[i]);
46 + }
47 + if (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW) {
48 + node->next = uevent_list;
49 + uevent_list = node;
50 + }
51 + else {
52 + for (walker = uevent_list; walker->next; walker = walker->next);
53 + walker->next = node;
54 + }
55 + for (i = 0; i < node->uevent->env_vars_c; i++) {
56 + unsetenv(node->uevent->env_vars[i].key);
57 + free(env[i]);
58 + }
59 + free(env);
60 + }
61 +}
62 +
63 +static void worker_fork_uevent_del(struct worker_fork_uevent_t *node) {
64 + struct worker_fork_uevent_t *walker;
65 +
66 + if (node == uevent_list) {
67 + uevent_list = node->next;
68 + }
69 + else {
70 + for (walker = uevent_list; walker->next; walker = walker->next)
71 + if (walker->next == node) walker->next = node->next;
72 + }
73 + worker_fork_uevent_free(node);
74 +}
75 +
76 +static void worker_fork_uevent_empty(void) {
77 + struct worker_fork_uevent_t *walker;
78 +
79 + if (!uevent_list) return;
80 + for (walker = uevent_list; walker->next; walker = walker->next) worker_fork_uevent_free(walker);
81 + uevent_list = NULL;
82 +}
83
84 /**
85 * Destroys data structures related to the given child ID (not PID).
86 @@ -315,6 +378,8 @@
87 struct worker_fork_ctx_t *ctx;
88 PRINTFUNC();
89
90 + uevent_list = NULL;
91 +
92 ctx = malloc(sizeof(struct worker_fork_ctx_t));
93 ctx->children = NULL;
94 ctx->children_count = 0;
95 @@ -376,6 +441,7 @@
96 free(ctx->children);
97 free(ctx);
98 global_ctx = NULL;
99 + worker_fork_uevent_empty();
100 }
101
102
103 @@ -384,15 +450,26 @@
104 int i;
105 struct worker_fork_child_t *child;
106 struct worker_fork_ctx_t *ctx = in_ctx;
107 + struct worker_fork_uevent_t *node, *walker;
108 + event_seqnum_t seqnum;
109 +
110 + worker_fork_uevent_add(ctx, uevent);
111 + walker = uevent_list;
112
113 /*
114 - * A big loop, because if we fail to process the event,
115 + * A big loop, because if we fail to process the events,
116 * we don't want to give up.
117 *
118 * TODO: Decide if we want to limit the number of attempts
119 * or set a time limit before reporting terminal failure.
120 */
121 do {
122 + /*
123 + * If more events are waiting, return to receive them
124 + */
125 + if (!seqnum_get(&seqnum) && seqnum > uevent->seqnum) break;
126 +
127 + node = walker;
128 worker_fork_update_children(ctx);
129
130 child = NULL;
131 @@ -407,9 +484,9 @@
132 * No child process is currently available.
133 */
134 if (child == NULL) {
135 - env = xmalloc(sizeof(char *) * uevent->env_vars_c);
136 - for (i = 0; i < uevent->env_vars_c; i++) {
137 - env[i] = alloc_env(uevent->env_vars[i].key, uevent->env_vars[i].value);
138 + env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
139 + for (i = 0; i < node->uevent->env_vars_c; i++) {
140 + env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
141 putenv(env[i]);
142 }
143
144 @@ -418,8 +495,11 @@
145 * can execute them in the main process?
146 */
147 if (ctx->always_fork == 0 && ctx->settings->dumb == 0 &&
148 - (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_MASK_SLOW) == 0) {
149 - action_perform(ctx->settings, uevent);
150 + (ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_MASK_SLOW) == 0) {
151 + action_perform(ctx->settings, node->uevent);
152 + walker = walker->next;
153 + worker_fork_uevent_del(node);
154 + if (walker) continue;
155 break;
156 }
157
158 @@ -427,11 +507,11 @@
159 * We have to fork off a new child.
160 */
161 if (ctx->children_count < ctx->max_children ||
162 - (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW))
163 + (ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_SLOW))
164 child = worker_fork_spawn(ctx);
165
166 - for (i = 0; i < uevent->env_vars_c; i++) {
167 - unsetenv(uevent->env_vars[i].key);
168 + for (i = 0; i < node->uevent->env_vars_c; i++) {
169 + unsetenv(node->uevent->env_vars[i].key);
170 free(env[i]);
171 }
172 free(env);
173 @@ -442,9 +522,14 @@
174 */
175 if (child != NULL) {
176 child->busy = 1;
177 - if (!worker_fork_relay_event(child->event_fd, uevent));
178 - break;
179 - child->busy = 0;
180 + if (worker_fork_relay_event(child->event_fd, node->uevent)) {
181 + child->busy = 0;
182 + continue;
183 + }
184 + walker = walker->next;
185 + worker_fork_uevent_del(node);
186 + if (walker) continue;
187 + break;
188 }
189
190 /*
191 diff -x '*~' -ur hotplug2-201/workers/worker_fork.h hotplug2-201.patched/workers/worker_fork.h
192 --- hotplug2-201/workers/worker_fork.h 2009-12-09 20:44:13.000000000 +0200
193 +++ hotplug2-201.patched/workers/worker_fork.h 2010-04-03 01:00:24.000000000 +0300
194 @@ -35,4 +35,9 @@
195 struct settings_t *settings;
196 };
197
198 +struct worker_fork_uevent_t {
199 + struct uevent_t *uevent;
200 + struct worker_fork_uevent_t *next;
201 +};
202 +
203 #endif