summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2009-06-11 19:34:50 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2009-06-11 19:34:50 +0200
commit5e696e022d8383bc7abe6e6ba37c2664679fe81f (patch)
tree34ab3159dda9efbdf352236a60a1b1236eb17525
parent0121fd74b805a6490f005c835b3994fa06487395 (diff)
conntrackd: allow to limit the number of simultaneous child processes
This patch allows to limit the number of simultaneous child processes. This is required by the next patch that replaces disposable handlers to commit and flush with permanent handlers. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/process.h11
-rw-r--r--src/process.c16
-rw-r--r--src/run.c3
-rw-r--r--src/sync-mode.c14
4 files changed, 34 insertions, 10 deletions
diff --git a/include/process.h b/include/process.h
index a7f07ea..9d29f22 100644
--- a/include/process.h
+++ b/include/process.h
@@ -1,14 +1,23 @@
#ifndef _PROCESS_H_
#define _PROCESS_H_
+enum process_type {
+ CTD_PROC_ANY, /* any type */
+ CTD_PROC_FLUSH, /* flush process */
+ CTD_PROC_COMMIT, /* commit process */
+};
+
+#define CTD_PROC_F_EXCL (1 << 0) /* only one process at a time */
+
struct child_process {
struct list_head head;
int pid;
+ int type;
void (*cb)(void *data);
void *data;
};
-int fork_process_new(void (*cb)(void *data), void *data);
+int fork_process_new(int type, int flags, void (*cb)(void *data), void *data);
int fork_process_delete(int pid);
#endif
diff --git a/src/process.c b/src/process.c
index 31e6e6f..c378f7a 100644
--- a/src/process.c
+++ b/src/process.c
@@ -22,20 +22,32 @@
static LIST_HEAD(process_list);
-int fork_process_new(void (*cb)(void *data), void *data)
+int fork_process_new(int type, int flags, void (*cb)(void *data), void *data)
{
- struct child_process *c;
+ struct child_process *c, *this;
int pid;
/* block SIGCHLD to avoid the access of the list concurrently */
sigprocmask(SIG_BLOCK, &STATE(block), NULL);
+ /* We only want one process of this type at the same time. This is
+ * useful if you want to prevent two child processes from accessing
+ * a shared descriptor at the same time. */
+ if (flags & CTD_PROC_F_EXCL) {
+ list_for_each_entry(this, &process_list, head) {
+ if (this->type == type) {
+ sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
+ return -1;
+ }
+ }
+ }
c = calloc(sizeof(struct child_process), 1);
if (c == NULL) {
sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
return -1;
}
+ c->type = type;
c->cb = cb;
c->data = data;
c->pid = pid = fork();
diff --git a/src/run.c b/src/run.c
index 21ff715..a0aea4f 100644
--- a/src/run.c
+++ b/src/run.c
@@ -218,7 +218,8 @@ void local_handler(int fd, void *data)
/* fork a child process that performs the flush operation,
* meanwhile the parent process handles events. */
- if (fork_process_new(flush_done_cb, h) == 0) {
+ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL,
+ flush_done_cb, h) == 0) {
nl_flush_conntrack_table(h);
exit(EXIT_SUCCESS);
}
diff --git a/src/sync-mode.c b/src/sync-mode.c
index 699a585..2da3604 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -229,7 +229,8 @@ static void do_reset_cache_alarm(struct alarm_block *a, void *data)
/* fork a child process that performs the flush operation,
* meanwhile the parent process handles events. */
- if (fork_process_new(flush_done_cb, h) == 0) {
+ if (fork_process_new(CTD_PROC_FLUSH, CTD_PROC_F_EXCL,
+ flush_done_cb, h) == 0) {
nl_flush_conntrack_table(h);
exit(EXIT_SUCCESS);
}
@@ -423,28 +424,28 @@ static int local_handler_sync(int fd, int type, void *data)
switch(type) {
case DUMP_INTERNAL:
- ret = fork_process_new(NULL, NULL);
+ ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
if (ret == 0) {
cache_dump(STATE_SYNC(internal), fd, NFCT_O_PLAIN);
exit(EXIT_SUCCESS);
}
break;
case DUMP_EXTERNAL:
- ret = fork_process_new(NULL, NULL);
+ ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
if (ret == 0) {
cache_dump(STATE_SYNC(external), fd, NFCT_O_PLAIN);
exit(EXIT_SUCCESS);
}
break;
case DUMP_INT_XML:
- ret = fork_process_new(NULL, NULL);
+ ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
if (ret == 0) {
cache_dump(STATE_SYNC(internal), fd, NFCT_O_XML);
exit(EXIT_SUCCESS);
}
break;
case DUMP_EXT_XML:
- ret = fork_process_new(NULL, NULL);
+ ret = fork_process_new(CTD_PROC_ANY, 0, NULL, NULL);
if (ret == 0) {
cache_dump(STATE_SYNC(external), fd, NFCT_O_XML);
exit(EXIT_SUCCESS);
@@ -465,7 +466,8 @@ static int local_handler_sync(int fd, int type, void *data)
origin_register(h, CTD_ORIGIN_COMMIT);
/* fork new process and insert it the process list */
- ret = fork_process_new(commit_done_cb, h);
+ ret = fork_process_new(CTD_PROC_COMMIT, CTD_PROC_F_EXCL,
+ commit_done_cb, h);
if (ret == 0) {
dlog(LOG_NOTICE, "committing external cache");
cache_commit(STATE_SYNC(external), h);