mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
Add thread to kill zombies, when child processes don't die immediately on
SIGHUP. (closes issue #13968) Reported by: eldadran Patches: 20090114__bug13968.diff.txt uploaded by Corydon76 (license 14) Tested by: eldadran git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@171120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -105,6 +105,8 @@ static char *descrip =
|
||||
|
||||
static int agidebug = 0;
|
||||
|
||||
static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL;
|
||||
|
||||
#define TONE_BLOCK_SIZE 200
|
||||
|
||||
/* Max time to connect to an AGI remote host */
|
||||
@@ -119,6 +121,13 @@ enum agi_result {
|
||||
AGI_RESULT_HANGUP
|
||||
};
|
||||
|
||||
struct zombie {
|
||||
pid_t pid;
|
||||
AST_LIST_ENTRY(zombie) list;
|
||||
};
|
||||
|
||||
static AST_LIST_HEAD_STATIC(zombies, zombie);
|
||||
|
||||
static int __attribute__((format(printf, 2, 3))) agi_debug_cli(int fd, char *fmt, ...)
|
||||
{
|
||||
char *stuff;
|
||||
@@ -1969,7 +1978,26 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
|
||||
usleep(1);
|
||||
}
|
||||
}
|
||||
waitpid(pid, status, WNOHANG);
|
||||
/* This is essentially doing the same as without WNOHANG, except that
|
||||
* it allows the main thread to proceed, even without the child PID
|
||||
* dying immediately (the child may be doing cleanup, etc.). Without
|
||||
* this code, zombie processes accumulate for as long as child
|
||||
* processes exist (which on busy systems may be never, filling up the
|
||||
* process table).
|
||||
*
|
||||
* Note that in trunk, we don't stop interaction at the hangup event
|
||||
* (instead we transparently switch to DeadAGI operation), so this is a
|
||||
* short-lived code addition.
|
||||
*/
|
||||
if (waitpid(pid, status, WNOHANG) == 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(readf);
|
||||
return returnstatus;
|
||||
@@ -2203,17 +2231,58 @@ static struct ast_cli_entry cli_agi[] = {
|
||||
dumpagihtml_help, NULL, &cli_dump_agihtml_deprecated },
|
||||
};
|
||||
|
||||
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(&zombies, 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. */
|
||||
poll(NULL, 0, 60000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
struct zombie *cur;
|
||||
ast_module_user_hangup_all();
|
||||
ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
|
||||
ast_unregister_application(eapp);
|
||||
ast_unregister_application(deadapp);
|
||||
return ast_unregister_application(app);
|
||||
res = ast_unregister_application(app);
|
||||
if (shaun_of_the_dead_thread != AST_PTHREADT_NULL) {
|
||||
pthread_cancel(shaun_of_the_dead_thread);
|
||||
pthread_kill(shaun_of_the_dead_thread, SIGURG);
|
||||
pthread_join(shaun_of_the_dead_thread, NULL);
|
||||
}
|
||||
while ((cur = AST_LIST_REMOVE_HEAD(&zombies, list))) {
|
||||
ast_free(cur);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
|
||||
ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
|
||||
ast_register_application(eapp, eagi_exec, esynopsis, descrip);
|
||||
|
Reference in New Issue
Block a user