summaryrefslogtreecommitdiff
path: root/package/hotplug2
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-06-25 09:47:58 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2007-06-25 09:47:58 +0000
commitaa9d23c30262874aa3aa38c30df1a29ce6cd1f30 (patch)
tree5b4c44ba4045e6bd6f6e36e2e10a8763a8798f13 /package/hotplug2
parent024945eed57f612ed801d23898b99ffd3fbd7f03 (diff)
hotplug2: add fork handling optimization (also fixes that pesky pppoe race condition in #1655)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7726 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/hotplug2')
-rw-r--r--package/hotplug2/patches/120-fork_handling.patch142
1 files changed, 142 insertions, 0 deletions
diff --git a/package/hotplug2/patches/120-fork_handling.patch b/package/hotplug2/patches/120-fork_handling.patch
new file mode 100644
index 0000000000..c234a6cb72
--- /dev/null
+++ b/package/hotplug2/patches/120-fork_handling.patch
@@ -0,0 +1,142 @@
+Index: hotplug2-0.9/hotplug2.c
+===================================================================
+--- hotplug2-0.9.orig/hotplug2.c 2007-06-25 11:36:44.800185312 +0200
++++ hotplug2-0.9/hotplug2.c 2007-06-25 11:39:08.318367232 +0200
+@@ -313,6 +313,17 @@
+ }
+
+ #ifdef HAVE_RULES
++static int action_needs_fork(struct hotplug2_event_t *event, struct rules_t *rules)
++{
++ int i, rv;
++
++ for (i = 0; i < rules->rules_c; i++) {
++ if (rule_needs_fork(event, &rules->rules[i]))
++ return 1;
++ }
++ return 0;
++}
++
+ void perform_action(struct hotplug2_event_t *event, struct rules_t *rules) {
+ int i, rv;
+
+@@ -565,14 +576,20 @@
+ cur_seqnum = strtoull(seqnum, NULL, 0);
+ if (cur_seqnum > highest_seqnum)
+ highest_seqnum = cur_seqnum;
+-
++
+ if ((dumb && tmpevent->action == ACTION_ADD && modalias != NULL) || (!dumb)) {
+- /*
+- * We have more children than we want. Wait until SIGCHLD handler reduces
+- * their numbers.
+- */
+- while (child_c >= max_child_c) {
+- usleep(HOTPLUG2_THROTTLE_INTERVAL);
++ int untracked = 0;
++
++ if (!dumb && !action_needs_fork(tmpevent, rules))
++ untracked = 1;
++ else {
++ /*
++ * We have more children than we want. Wait until SIGCHLD handler reduces
++ * their numbers.
++ */
++ while (child_c >= max_child_c) {
++ usleep(HOTPLUG2_THROTTLE_INTERVAL);
++ }
+ }
+
+ sigemptyset(&block_mask);
+@@ -595,13 +612,16 @@
+ break;
+ default:
+ DBG("spawn", "spawning: %d.", p);
+- child = add_child(child, p, cur_seqnum);
+- child_c++;
++ if (!untracked) {
++ child = add_child(child, p, cur_seqnum);
++ child_c++;
++ }
+ break;
+ }
+ sigprocmask(SIG_UNBLOCK, &block_mask, 0);
+ }
+
++done:
+ free_hotplug2_event(tmpevent);
+ }
+
+Index: hotplug2-0.9/rules.c
+===================================================================
+--- hotplug2-0.9.orig/rules.c 2007-06-25 11:36:44.801185160 +0200
++++ hotplug2-0.9/rules.c 2007-06-25 11:36:44.822181968 +0200
+@@ -363,6 +363,41 @@
+ return EVAL_NOT_AVAILABLE;
+ }
+
++int rule_needs_fork(struct hotplug2_event_t *event, struct rule_t *rule)
++{
++ int i, last_rv;
++
++ for (i = 0; i < rule->conditions_c; i++) {
++ if (rule_condition_eval(event, &(rule->conditions[i])) != EVAL_MATCH)
++ return 0;
++ }
++ for (i = 0; i < rule->actions_c; i++) {
++ switch (rule->actions[i].type) {
++ case ACT_STOP_PROCESSING:
++ return 0;
++ break;
++ case ACT_STOP_IF_FAILED:
++ if (last_rv != 0)
++ return 0;
++ break;
++ case ACT_NEXT_EVENT:
++ return 0;
++ break;
++ case ACT_NEXT_IF_FAILED:
++ if (last_rv != 0)
++ return 0;
++ break;
++ case ACT_RUN_SHELL:
++ return 1;
++ break;
++ case ACT_RUN_NOSHELL:
++ return 1;
++ break;
++ }
++ }
++ return 0;
++}
++
+ int rule_execute(struct hotplug2_event_t *event, struct rule_t *rule) {
+ int i, last_rv;
+
+Index: hotplug2-0.9/rules.h
+===================================================================
+--- hotplug2-0.9.orig/rules.h 2007-06-25 11:36:44.801185160 +0200
++++ hotplug2-0.9/rules.h 2007-06-25 11:36:44.822181968 +0200
+@@ -77,5 +77,6 @@
+ int rule_execute(struct hotplug2_event_t *, struct rule_t *);
+ void rules_free(struct rules_t *);
+ struct rules_t *rules_from_config(char *);
++int rule_needs_fork(struct hotplug2_event_t *event, struct rule_t *rule);
+
+ #endif /* ifndef RULES_H*/
+Index: hotplug2-0.9/childlist.c
+===================================================================
+--- hotplug2-0.9.orig/childlist.c 2007-06-25 11:40:23.477941240 +0200
++++ hotplug2-0.9/childlist.c 2007-06-25 11:40:48.164188360 +0200
+@@ -41,10 +41,8 @@
+ struct hotplug2_child_t *remove_child_by_pid(struct hotplug2_child_t *child, pid_t pid, event_seqnum_t *largest_seqnum, int *child_c) {
+ struct hotplug2_child_t *tmp_child;
+
+- if (child == NULL) {
+- ERROR("remove_child_by_pid", "Invalid child list passed (NULL).");
++ if (child == NULL)
+ return NULL;
+- }
+
+ tmp_child = child;
+