mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
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
This commit is contained in:
61
main/app.c
61
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 */
|
||||
|
Reference in New Issue
Block a user