2
0

140-worker_fork_fix.patch 6.3 KB

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