diff options
-rw-r--r-- | include/process.h | 11 | ||||
-rw-r--r-- | src/process.c | 16 | ||||
-rw-r--r-- | src/run.c | 3 | ||||
-rw-r--r-- | src/sync-mode.c | 14 |
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(); @@ -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); |