160-event_block_fix.patch 5.8 KB

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