aboutsummaryrefslogtreecommitdiffstats
path: root/.gitignore
Commit message (Expand)AuthorAgeFilesLines
* build: add integration for managing opkg package feed keysFelix Fietkau2015-04-061-1/+2
* add git-src to .gitignoreJohn Crispin2014-01-121-1/+2
* .gitignore: Ignore Emacs editor generated filesVasilis Tsiligiannis2011-10-311-0/+4
* add vim temp files (*~) to .gitignoreJo-Philipp Wich2011-04-291-0/+1
* gitignore: add *.rej and *.orig to .gitignoreFlorian Fainelli2011-04-031-0/+2
* .gitignore: add *.o and .DS_Store by default - apparently some git versions d...Felix Fietkau2010-12-041-0/+2
* .gitignore: Undo accidental commit.Daniel Dickinson2010-05-101-0/+3
* brcm-2.4: Fixed preinit and failsafe switch configurationDaniel Dickinson2010-05-101-3/+0
* .gitignore: ignore vim swap filesFelix Fietkau2009-12-161-0/+1
* add logs/ to .gitignoreFelix Fietkau2009-04-241-0/+1
* add feeds.conf to .gitignoreFelix Fietkau2008-09-231-0/+1
* add missing gitignore change for build environmentsFelix Fietkau2008-08-061-0/+1
* update svn:ignore and .gitignoreFelix Fietkau2008-06-061-6/+6
* add package/openwrt-packages to .gitignoreFelix Fietkau2008-02-091-0/+1
* add package/feeds to .gitignoreFelix Fietkau2007-10-131-0/+1
* add feeds to .gitignoreFelix Fietkau2007-10-091-0/+1
* update svn and git ignore settingsFelix Fietkau2007-08-071-1/+1
* make top-level .gitignore only apply to top-level files/directories (#1960)Felix Fietkau2007-06-251-8/+8
* Add gitignore filesFelix Fietkau2007-05-291-0/+8
c0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
--- a/uevent.c
+++ b/uevent.c
@@ -132,6 +132,8 @@ struct uevent_t *uevent_dup(const struct
 	
 	dest = xmalloc(sizeof(struct uevent_t));
 	dest->action = src->action;
+	dest->seqnum = src->seqnum;
+	dest->action_str = strdup(src->action_str);
 	dest->env_vars_c = src->env_vars_c;
 	dest->env_vars = xmalloc(sizeof(struct env_var_t) * dest->env_vars_c);
 	dest->plain_s = src->plain_s;
--- a/workers/worker_fork.c
+++ b/workers/worker_fork.c
@@ -1,6 +1,69 @@
 #include "worker_fork.h"
 
 static struct worker_fork_ctx_t *global_ctx;
+static struct worker_fork_uevent_t *uevent_list;
+
+static void worker_fork_uevent_free(struct worker_fork_uevent_t *node) {
+	uevent_free(node->uevent);
+	free(node);
+}
+
+static void worker_fork_uevent_add(void *in_ctx, struct uevent_t *uevent) {
+	char **env;
+	int i;
+	struct worker_fork_ctx_t *ctx = in_ctx;
+	struct worker_fork_uevent_t *node, *walker;
+
+	node = malloc(sizeof (struct worker_fork_uevent_t));
+	node->uevent = uevent_dup(uevent);
+	node->next = NULL;
+
+	if (!uevent_list) uevent_list = node;
+	else {
+		/*
+		 * Put events that need to fork first and in reverse order
+		 */
+		env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
+		for (i = 0; i < node->uevent->env_vars_c; i++) {
+			env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
+			putenv(env[i]);
+		}
+		if (ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW) {
+			node->next = uevent_list;
+			uevent_list = node;
+		}
+		else {
+			for (walker = uevent_list; walker->next; walker = walker->next);
+			walker->next = node;
+		}
+		for (i = 0; i < node->uevent->env_vars_c; i++) {
+			unsetenv(node->uevent->env_vars[i].key);
+			free(env[i]);
+		}
+		free(env);
+	}
+}
+
+static void worker_fork_uevent_del(struct worker_fork_uevent_t *node) {
+	struct worker_fork_uevent_t *walker;
+
+	if (node == uevent_list) {
+		uevent_list = node->next;
+	}
+	else {
+		for (walker = uevent_list; walker->next; walker = walker->next)
+			if (walker->next == node) walker->next = node->next;
+	}
+	worker_fork_uevent_free(node);
+}
+
+static void worker_fork_uevent_empty(void) {
+	struct worker_fork_uevent_t *walker;
+
+	if (!uevent_list) return;
+	for (walker = uevent_list; walker->next; walker = walker->next) worker_fork_uevent_free(walker);
+	uevent_list = NULL;
+}
 
 /**
  * Destroys data structures related to the given child ID (not PID).
@@ -315,6 +378,8 @@ static void *worker_fork_init(struct set
 	struct worker_fork_ctx_t *ctx;
 	PRINTFUNC();
 
+	uevent_list = NULL;
+
 	ctx = malloc(sizeof(struct worker_fork_ctx_t));
 	ctx->children = NULL;
 	ctx->children_count = 0;
@@ -376,6 +441,7 @@ static void worker_fork_deinit(void *in_
 	free(ctx->children);
 	free(ctx);
 	global_ctx = NULL;
+	worker_fork_uevent_empty();
 }
 
 
@@ -384,15 +450,26 @@ static int worker_fork_process(void *in_
 	int i;
 	struct worker_fork_child_t *child;
 	struct worker_fork_ctx_t *ctx = in_ctx;
+	struct worker_fork_uevent_t *node, *walker;
+	event_seqnum_t seqnum;
+
+	worker_fork_uevent_add(ctx, uevent);
+	walker = uevent_list;
 
 	/*
-	 * A big loop, because if we fail to process the event,
+	 * A big loop, because if we fail to process the events,
 	 * we don't want to give up.
 	 *
 	 * TODO: Decide if we want to limit the number of attempts
 	 * or set a time limit before reporting terminal failure.
 	 */
 	do {
+		/*
+		 * If more events are waiting, return to receive them
+		 */
+		if (!seqnum_get(&seqnum) && seqnum > uevent->seqnum) break;
+
+		node = walker;
 		worker_fork_update_children(ctx);
 
 		child = NULL;
@@ -407,9 +484,9 @@ static int worker_fork_process(void *in_
 		 * No child process is currently available.
 		 */
 		if (child == NULL) {
-			env = xmalloc(sizeof(char *) * uevent->env_vars_c);
-			for (i = 0; i < uevent->env_vars_c; i++) {
-				env[i] = alloc_env(uevent->env_vars[i].key, uevent->env_vars[i].value);
+			env = xmalloc(sizeof(char *) * node->uevent->env_vars_c);
+			for (i = 0; i < node->uevent->env_vars_c; i++) {
+				env[i] = alloc_env(node->uevent->env_vars[i].key, node->uevent->env_vars[i].value);
 				putenv(env[i]);
 			}
 
@@ -418,8 +495,11 @@ static int worker_fork_process(void *in_
 			 * can execute them in the main process?
 			 */
 			if (ctx->always_fork == 0 && ctx->settings->dumb == 0 && 
-			(ruleset_flags(&ctx->settings->rules, uevent) & FLAG_MASK_SLOW) == 0) {
-				action_perform(ctx->settings, uevent);
+			(ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_MASK_SLOW) == 0) {
+				action_perform(ctx->settings, node->uevent);
+				walker = walker->next;
+				worker_fork_uevent_del(node);
+				if (walker) continue;
 				break;
 			}
 			
@@ -427,11 +507,11 @@ static int worker_fork_process(void *in_
 			 * We have to fork off a new child.
 			 */
 			if (ctx->children_count < ctx->max_children || 
-			(ruleset_flags(&ctx->settings->rules, uevent) & FLAG_SLOW))
+			(ruleset_flags(&ctx->settings->rules, node->uevent) & FLAG_SLOW))
 				child = worker_fork_spawn(ctx);
 
-			for (i = 0; i < uevent->env_vars_c; i++) {
-				unsetenv(uevent->env_vars[i].key);
+			for (i = 0; i < node->uevent->env_vars_c; i++) {
+				unsetenv(node->uevent->env_vars[i].key);
 				free(env[i]);
 			}
 			free(env);
@@ -442,9 +522,14 @@ static int worker_fork_process(void *in_
 		 */
 		if (child != NULL) {
 			child->busy = 1;
-			if (!worker_fork_relay_event(child->event_fd, uevent));
-				break;
-			child->busy = 0;
+			if (worker_fork_relay_event(child->event_fd, node->uevent)) {
+				child->busy = 0;
+				continue;
+			}
+			walker = walker->next;
+			worker_fork_uevent_del(node);
+			if (walker) continue;
+			break;
 		}
 
 		/* 
--- a/workers/worker_fork.h
+++ b/workers/worker_fork.h
@@ -35,4 +35,9 @@ struct worker_fork_ctx_t {
 	struct settings_t			*settings;
 };
 
+struct worker_fork_uevent_t {
+	struct uevent_t *uevent;
+	struct worker_fork_uevent_t *next;
+};
+
 #endif