diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2011-01-19 20:33:30 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2011-01-19 20:33:30 +0000 |
commit | f8bbf4bfa26d7a5cd64875d38968c568a5f7e5c2 (patch) | |
tree | df6ed35727904720e3d5ae002b58988bbd25599c /main | |
parent | dcc2a9ea5b2e5399400ed6577d4bfb2c680960bc (diff) |
Merged revisions 302634 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
................
r302634 | tilghman | 2011-01-19 14:24:57 -0600 (Wed, 19 Jan 2011) | 22 lines
Merged revisions 302599 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.6.2
........
r302599 | tilghman | 2011-01-19 14:13:24 -0600 (Wed, 19 Jan 2011) | 15 lines
Kill zombies.
When we ast_safe_fork() with a non-zero argument, we're expected to reap our
own zombies. On a zero argument, however, the zombies are only reaped when
there aren't any non-zero forked children alive. At other times, we
accumulate zombies. This code is forward ported from res_agi in 1.4, so that
forked children are always reaped, thus preventing an accumulation of zombie
processes.
(closes issue #18515)
Reported by: ernied
Patches:
20101221__issue18515.diff.txt uploaded by tilghman (license 14)
Tested by: ernied
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@302644 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r-- | main/app.c | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/main/app.c b/main/app.c index 526927140..0054c4cde 100644 --- a/main/app.c +++ b/main/app.c @@ -30,10 +30,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif -#include <regex.h> -#include <sys/file.h> /* added this to allow to compile, sorry! */ -#include <signal.h> +#include <regex.h> /* for regcomp(3) */ +#include <sys/file.h> /* for flock(2) */ +#include <signal.h> /* for pthread_sigmask(3) */ #include <stdlib.h> /* for closefrom(3) */ +#include <sys/types.h> +#include <sys/wait.h> /* for waitpid(2) */ +#ifndef HAVE_CLOSEFROM +#include <dirent.h> /* for opendir(3) */ +#endif #ifdef HAVE_CAP #include <sys/capability.h> #endif /* HAVE_CAP */ @@ -52,6 +57,41 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf); +static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL; + +struct zombie { + pid_t pid; + AST_LIST_ENTRY(zombie) list; +}; + +static AST_LIST_HEAD_STATIC(zombies, zombie); + +static void *shaun_of_the_dead(void *data) +{ + struct zombie *cur; + int status; + for (;;) { + if (!AST_LIST_EMPTY(&zombies)) { + /* Don't allow cancellation while we have a lock. */ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + AST_LIST_LOCK(&zombies); + AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) { + if (waitpid(cur->pid, &status, WNOHANG) != 0) { + AST_LIST_REMOVE_CURRENT(list); + ast_free(cur); + } + } + AST_LIST_TRAVERSE_SAFE_END + AST_LIST_UNLOCK(&zombies); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + } + pthread_testcancel(); + /* Wait for 60 seconds, without engaging in a busy loop. */ + ast_poll(NULL, 0, AST_LIST_FIRST(&zombies) ? 5000 : 60000); + } + return NULL; +} + #define AST_MAX_FORMATS 10 @@ -2061,6 +2101,21 @@ int ast_safe_fork(int stop_reaper) if (pid != 0) { /* Fork failed or parent */ pthread_sigmask(SIG_SETMASK, &old_set, NULL); + if (!stop_reaper && pid > 0) { + struct zombie *cur = ast_calloc(1, sizeof(*cur)); + if (cur) { + cur->pid = pid; + AST_LIST_LOCK(&zombies); + AST_LIST_INSERT_TAIL(&zombies, cur, list); + AST_LIST_UNLOCK(&zombies); + if (shaun_of_the_dead_thread == AST_PTHREADT_NULL) { + if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) { + ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n"); + shaun_of_the_dead_thread = AST_PTHREADT_NULL; + } + } + } + } return pid; } else { /* Child */ |