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