fd037b122a4b9e679f7823a51701f728d2639df3
[openwrt.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