2012-05-03 05:42:41 +04:00
/*
functions to track and manage processes
Copyright ( C ) Ronnie Sahlberg 2012
This program 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 3 of the License , or
( at your option ) any later version .
This program 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 , see < http : //www.gnu.org/licenses/>.
*/
2015-10-26 08:50:46 +03:00
# include "replace.h"
2012-05-03 05:42:41 +04:00
# include "system/wait.h"
2015-10-26 08:50:46 +03:00
# include "system/network.h"
# include <talloc.h>
# include <tevent.h>
# include "lib/util/debug.h"
# include "ctdb_logging.h"
# include "ctdb_private.h"
# include "ctdb_client.h"
# include "common/rb_tree.h"
2015-10-23 06:11:53 +03:00
# include "common/system.h"
2015-10-23 06:17:34 +03:00
# include "common/common.h"
2012-05-03 05:42:41 +04:00
2013-04-16 05:11:11 +04:00
void ctdb_set_child_info ( TALLOC_CTX * mem_ctx , const char * child_name_fmt , . . . )
{
if ( child_name_fmt ! = NULL ) {
va_list ap ;
char * t ;
va_start ( ap , child_name_fmt ) ;
t = talloc_vasprintf ( mem_ctx , child_name_fmt , ap ) ;
debug_extra = talloc_asprintf ( mem_ctx , " %s: " , t ) ;
talloc_free ( t ) ;
va_end ( ap ) ;
}
}
2013-11-19 09:13:20 +04:00
void ctdb_track_child ( struct ctdb_context * ctdb , pid_t pid )
{
char * process ;
/* Only CTDB main daemon should track child processes */
if ( getpid ( ) ! = ctdb - > ctdbd_pid ) {
return ;
}
process = talloc_asprintf ( ctdb - > child_processes , " process:%d " , ( int ) pid ) ;
trbt_insert32 ( ctdb - > child_processes , pid , process ) ;
}
2012-05-03 05:42:41 +04:00
/*
* This function forks a child process and drops the realtime
* scheduler for the child process .
*/
2014-08-08 06:51:03 +04:00
pid_t ctdb_fork ( struct ctdb_context * ctdb )
2012-05-03 05:42:41 +04:00
{
pid_t pid ;
pid = fork ( ) ;
if ( pid = = - 1 ) {
return - 1 ;
}
if ( pid = = 0 ) {
2013-04-15 10:14:40 +04:00
ctdb_set_child_info ( ctdb , NULL ) ;
2012-10-02 05:51:24 +04:00
/* Close the Unix Domain socket and the TCP socket.
* This ensures that none of the child processes will
* look like the main daemon when it is not running .
* tevent needs to be stopped before closing sockets .
*/
if ( ctdb - > ev ! = NULL ) {
talloc_free ( ctdb - > ev ) ;
ctdb - > ev = NULL ;
}
if ( ctdb - > daemon . sd ! = - 1 ) {
close ( ctdb - > daemon . sd ) ;
ctdb - > daemon . sd = - 1 ;
}
if ( ctdb - > methods ! = NULL ) {
ctdb - > methods - > shutdown ( ctdb ) ;
}
/* The child does not need to be realtime */
2012-05-03 05:42:41 +04:00
if ( ctdb - > do_setsched ) {
2014-06-10 10:48:03 +04:00
reset_scheduler ( ) ;
2012-05-03 05:42:41 +04:00
}
ctdb - > can_send_controls = false ;
2013-02-05 05:09:36 +04:00
2012-05-03 05:42:41 +04:00
return 0 ;
}
2013-11-19 09:13:20 +04:00
ctdb_track_child ( ctdb , pid ) ;
2012-05-03 05:42:41 +04:00
return pid ;
}
static void ctdb_sigchld_handler ( struct tevent_context * ev ,
struct tevent_signal * te , int signum , int count ,
void * dont_care ,
void * private_data )
{
struct ctdb_context * ctdb = talloc_get_type ( private_data , struct ctdb_context ) ;
int status ;
pid_t pid = - 1 ;
while ( pid ! = 0 ) {
pid = waitpid ( - 1 , & status , WNOHANG ) ;
if ( pid = = - 1 ) {
DEBUG ( DEBUG_ERR , ( __location__ " waitpid() returned error. errno:%d \n " , errno ) ) ;
return ;
}
if ( pid > 0 ) {
char * process ;
if ( getpid ( ) ! = ctdb - > ctdbd_pid ) {
continue ;
}
process = trbt_lookup32 ( ctdb - > child_processes , pid ) ;
if ( process = = NULL ) {
DEBUG ( DEBUG_ERR , ( " Got SIGCHLD from pid:%d we didn not spawn with ctdb_fork \n " , pid ) ) ;
}
DEBUG ( DEBUG_DEBUG , ( " SIGCHLD from %d %s \n " , ( int ) pid , process ) ) ;
talloc_free ( process ) ;
}
}
}
struct tevent_signal *
ctdb_init_sigchld ( struct ctdb_context * ctdb )
{
struct tevent_signal * se ;
ctdb - > child_processes = trbt_create ( ctdb , 0 ) ;
se = tevent_add_signal ( ctdb - > ev , ctdb , SIGCHLD , 0 , ctdb_sigchld_handler , ctdb ) ;
return se ;
}
int
ctdb_kill ( struct ctdb_context * ctdb , pid_t pid , int signum )
{
char * process ;
if ( signum = = 0 ) {
return kill ( pid , signum ) ;
}
if ( getpid ( ) ! = ctdb - > ctdbd_pid ) {
return kill ( pid , signum ) ;
}
process = trbt_lookup32 ( ctdb - > child_processes , pid ) ;
if ( process = = NULL ) {
DEBUG ( DEBUG_ERR , ( " ctdb_kill: trying to kill(%d, %d) a process that does not exist \n " , pid , signum ) ) ;
return 0 ;
}
return kill ( pid , signum ) ;
}