You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules_s/exec/kill.c

175 lines
4.3 KiB

/*
*
* $Id$
*
* in this file, we implement the ability to send a kill signal to
* a child after some time; its a quick ugly hack, for example kill
* is sent without any knowledge whether the kid is still alive
*
* also, it was never compiled without FAST_LOCK -- nothing will
* work if you turn it off
*
* there is also an ugly s/HACK
*
* and last but not least -- we don't know the child pid (we use popen)
* so we cannot close anyway
*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of ser, a free SIP server.
*
* ser is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* ser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* History:
* --------
* 2003-03-11 changed to the new locking scheme: locking.h (andrei)
*/
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include "../../mem/shm_mem.h"
#include "../../dprint.h"
#include "../../timer.h"
#include "../../locking.h"
#include "kill.h"
static gen_lock_t *kill_lock;
static struct timer_list kill_list;
#define lock() lock_get(kill_lock)
#define unlock() lock_release(kill_lock)
/* copy and paste from TM -- might consider putting in better
in some utils part of core
*/
static void timer_routine(unsigned int ticks , void * attr)
{
struct timer_link *tl, *tmp_tl, *end, *ret;
int killr;
/* check if it worth entering the lock */
if (kill_list.first_tl.next_tl==&kill_list.last_tl
|| kill_list.first_tl.next_tl->time_out > ticks )
return;
lock();
end = &kill_list.last_tl;
tl = kill_list.first_tl.next_tl;
while( tl!=end && tl->time_out <= ticks ) {
tl=tl->next_tl;
}
/* nothing to delete found */
if (tl->prev_tl==&kill_list.first_tl) {
unlock();
return;
}
/* the detached list begins with current beginning */
ret = kill_list.first_tl.next_tl;
/* and we mark the end of the split list */
tl->prev_tl->next_tl = 0;
/* the shortened list starts from where we suspended */
kill_list.first_tl.next_tl = tl;
tl->prev_tl = & kill_list.first_tl;
unlock();
/* process the list now */
while (ret) {
tmp_tl=ret->next_tl;
ret->next_tl=ret->prev_tl=0;
if (ret->time_out>0) {
killr=kill(ret->pid, SIGTERM );
DBG("DEBUG: child process (%d) kill status: %d\n",
ret->pid, killr );
}
shm_free(ret);
ret=tmp_tl;
}
}
int schedule_to_kill( int pid )
{
struct timer_link *tl;
tl=shm_malloc( sizeof(struct timer_link) );
if (tl==0) {
LOG(L_ERR, "ERROR: schedule_to_kill: no shmem\n");
return -1;
}
memset(tl, 0, sizeof(struct timer_link) );
lock();
tl->pid=pid;
tl->time_out=get_ticks()+time_to_kill;
tl->prev_tl=kill_list.last_tl.prev_tl;
tl->next_tl=&kill_list.last_tl;
kill_list.last_tl.prev_tl=tl;
tl->prev_tl->next_tl=tl;
unlock();
return 1;
}
int initialize_kill()
{
/* if disabled ... */
if (time_to_kill==0) return 1;
if ((register_timer( timer_routine,
0 /* param */, 1 /* period */)<0)) {
LOG(L_ERR, "ERROR: kill_initialize: no exec timer registered\n");
return -1;
}
kill_list.first_tl.next_tl=&kill_list.last_tl;
kill_list.last_tl.prev_tl=&kill_list.first_tl;
kill_list.first_tl.prev_tl=
kill_list.last_tl.next_tl = 0;
kill_list.last_tl.time_out=-1;
kill_lock=lock_alloc();
if (kill_lock==0) {
LOG(L_ERR, "ERROR: initialize_kill: no mem for mutex\n");
return -1;
}
lock_init(kill_lock);
DBG("DEBUG: kill initialized\n");
return 1;
}
void destroy_kill()
{
/* if disabled ... */
if (time_to_kill==0)
return;
if (kill_lock){
lock_destroy(kill_lock);
lock_dealloc(kill_lock);
}
return;
}