/* ******************************************************************************* * Copyright (c) 1997 Martin Poole * ******************************************************************************* ** ** WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! ** ** Any changes to be made to this file should first be checked with ** mplib1 source control for library integrity. ** ** mplib1 source control can be reached at mplib1@quatermass.co.uk ** * * System : * Subsystem : * Module : * $Source: /home/cvs/cvsroot/onelan/onelan/src/mplib1/util/watch_kill.c,v $ * $Author: mpoole $ * $Date: 2002/10/07 09:37:30 $ * $Revision: 1.2 $ * Purpose : * ******************************************************************************* * * Change History * * $Log: watch_kill.c,v $ * Revision 1.2 2002/10/07 09:37:30 mpoole * Initial checkin of mplib1-3.1.0 * * Revision 1.1 2002/10/07 09:37:09 mpoole * Initial checkin of mplib1-3.1.0 * * * ******************************************************************************* */ #ident "$Header: /home/cvs/cvsroot/onelan/onelan/src/mplib1/util/watch_kill.c,v 1.2 2002/10/07 09:37:30 mpoole Exp $" /* ------------------------------------------------------------------ Include files ------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "watchdog.h" /* ------------------------------------------------------------------ structures / defines ------------------------------------------------------------------ */ struct kill_pid { dl_Node_t kill_node; pid_t pid; int killstate; int in_shared; time_t wlimit; char pid_name[PID_STR_LEN]; }; static dl_List_t kill_list; static int done_init=0; /* ------------------------------------------------------------------ Code starts here ------------------------------------------------------------------ */ static void Init_Kill_List( void ) { if (done_init==0) { done_init = 1; dl_Init_List( &kill_list, LN_IGNORECASE ); } return; } static int free_killer( struct kill_pid *thisone ) { dl_Remove_Node( &thisone->kill_node ); free(thisone); return(1); } static void check_a_kill( struct kill_pid *killp, FILE *fp ) { time_t now; int nx; (void)time( &now ); if ( killp->pid == (pid_t)0 || is_pid_dead( killp->pid ) != 0 ) { /* Not around, remove from list */ free_killer( killp ); } else if ( now > killp->wlimit ) { /* advance the kill state */ switch( killp->killstate ) { case 0 : /* first case, shouldn't happen, but just in case */ fprintfile( fp, "check_a_kill: SIGINT on pid %d\n", killp->pid ); nx = kill( killp->pid, SIGINT ); if (nx==-1 && errno==EPERM) { fprintfile( fp, "check_a_kill: No permissions to kill\n" ); free_killer( killp ); killp=NULL; break; } nx = get_config_int( "KILL_DELAY_INT" ); if (nx==0) nx = 15; killp->wlimit = now + nx; killp->killstate++; break; case 1 : /* get more nasty */ fprintfile( fp, "check_a_kill: SIGTERM on pid %d\n", killp->pid ); kill( killp->pid, SIGTERM ); nx = get_config_int( "KILL_DELAY_TERM" ); if (nx==0) nx = 5; killp->wlimit = now + nx; killp->killstate++; break; case 2 : /* Captive bolt gun */ fprintfile( fp, "check_a_kill: SIGKILL on pid %d\n", killp->pid ); kill( killp->pid, SIGKILL ); killp->wlimit = now + 2; killp->killstate++; break; default : fprintfile( fp, "check_a_kill: SIGKILL on pid %d (WILL NOT DIE)\n", killp->pid ); kill( killp->pid, SIGKILL ); killp->wlimit = now + 2; break; } if (killp && killp->in_shared) Inform_Process_Str( get_comms_hint(), killp->pid_name ); } return; } static struct kill_pid * find_kill( pid_t pid ) { char t_pid[PID_STR_LEN]; struct kill_pid *killp; Init_Kill_List(); gen_pid_str( t_pid, pid ); /* fprintfile( stderr, "find_kill: (%s)(%ld)\n", t_pid, pid );*/ killp = dl_Find_Item_By_Name( &kill_list, t_pid ); return(killp); } static struct kill_pid * new_kill( pid_t pid, int in_shared ) { struct kill_pid *killp; killp = find_kill( pid ); if (! killp ) { killp = malloc( sizeof(struct kill_pid ) ); if (!killp) return(NULL); memset( killp, '\0', sizeof(struct kill_pid) ); gen_pid_str( killp->pid_name, pid ); killp->pid = pid; killp->killstate = 0; killp->in_shared = in_shared; killp->wlimit = time(NULL) -1; /* so that signalling starts now */ dl_Init_Node( &killp->kill_node, killp->pid_name, killp ); } return(killp); } int kill_pid( pid_t thispid, int in_shared, FILE *fp ) { struct kill_pid *killp; Init_Kill_List(); if (thispid) { killp = find_kill( thispid ); if (!killp) { /* New entry in kill list */ killp = new_kill( thispid, in_shared ); if (!killp) { fprintfile(fp, "Unable to allocate kill_pid structure: PID %d manually signalled", thispid ); kill( thispid, SIGINT ); return(0); } else { dl_Add_Head( &kill_list, &killp->kill_node ); check_a_kill( killp, fp ); } }else check_a_kill( killp, fp ); } return(0); } static void check_tlimit( struct kill_pid *killp, int *iptr ) { time_t now; int t; now = time(NULL); t = (killp->wlimit - now); if ( t > 0 && t < *iptr ) { *iptr = t; } if (*iptr == 0) *iptr = 1; /* always return non-zero, if anything in the list */ return; } int check_kills( FILE *fp ) { int ns=0; Init_Kill_List(); dl_Walk_List( &kill_list, (dl_Walk_List_t)check_a_kill, fp ); dl_Walk_List( &kill_list, (dl_Walk_List_t)check_tlimit, &ns ); return( ns ); } /* -- End of File -- */