LCOV - code coverage report
Current view: top level - app/fddev/configure - kill.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 109 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 6 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #include "../../fdctl/configure/configure.h"
       3             : 
       4             : #include <stdio.h>
       5             : #include <dirent.h>
       6             : #include <signal.h>
       7             : #include <sys/stat.h>
       8             : #include <sys/types.h>
       9             : 
      10           0 : #define NAME "kill"
      11             : 
      12             : static void
      13             : init_perm( fd_caps_ctx_t *  caps,
      14           0 :            config_t * const config ) {
      15           0 :   (void)config;
      16           0 :   fd_caps_check_root( caps, NAME, "check all open file descriptors in `/proc/`" );
      17           0 : }
      18             : 
      19             : static void
      20             : cmdline( char * buf,
      21             :          size_t len,
      22           0 :          ulong  pid ) {
      23           0 :   char path[ PATH_MAX ];
      24           0 :   FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/proc/%lu/cmdline", pid ) );
      25             : 
      26           0 :   FILE * fp = fopen( path, "r" );
      27           0 :   if( FD_UNLIKELY( !fp && errno==ENOENT ) ) {
      28           0 :     buf[ 0 ] = '\0';
      29           0 :     return;
      30           0 :   }
      31           0 :   if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "error opening `/proc/%lu/cmdline` (%i-%s)", pid, errno, fd_io_strerror( errno ) ));
      32             : 
      33           0 :   ulong read = fread( buf, 1, len - 1, fp );
      34           0 :   if( FD_UNLIKELY( ferror( fp ) ) ) FD_LOG_ERR(( "error reading `/proc/%lu/cmdline` (%i-%s)", pid, errno, fd_io_strerror( errno ) ));
      35           0 :   if( FD_UNLIKELY( fclose( fp ) ) ) FD_LOG_ERR(( "error closing `/proc/%lu/cmdline` (%i-%s)", pid, errno, fd_io_strerror( errno ) ));
      36             : 
      37           0 :   buf[ read ] = '\0';
      38           0 : }
      39             : 
      40             : static int
      41             : maybe_kill( config_t * const config,
      42           0 :             ulong            pid ) {
      43           0 :   int killed = 0;
      44             : 
      45           0 :   char proc_cmdline[ PATH_MAX ];
      46           0 :   cmdline( proc_cmdline, PATH_MAX, pid );
      47             : 
      48           0 :   ulong cmdline_len = strlen( proc_cmdline );
      49           0 :   if( FD_LIKELY( cmdline_len>=5UL ) ) {
      50           0 :     if( FD_UNLIKELY( !strcmp( proc_cmdline + (cmdline_len-5), "fddev" ) ) ) {
      51           0 :       killed = 1;
      52           0 :       FD_LOG_NOTICE(( "killing process `%s` (%lu): is fddev", proc_cmdline, pid ));
      53           0 :       if( FD_UNLIKELY( -1==kill( (int)pid, SIGKILL ) && errno!=ESRCH ) ) FD_LOG_ERR(( "kill failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      54           0 :     } else if( FD_UNLIKELY( !strcmp( proc_cmdline + (cmdline_len-5), "fdctl" ) ) ) {
      55           0 :       killed = 1;
      56           0 :       FD_LOG_NOTICE(( "killing process `%s` (%lu): is fdctl", proc_cmdline, pid ));
      57           0 :       if( FD_UNLIKELY( -1==kill( (int)pid, SIGKILL ) && errno!=ESRCH ) ) FD_LOG_ERR(( "kill failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      58           0 :     }
      59           0 :   }
      60             : 
      61           0 :   if( FD_UNLIKELY( killed ) ) return killed;
      62             : 
      63           0 :   char path[ PATH_MAX ];
      64           0 :   FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/proc/%lu/maps", pid ) );
      65           0 :   FILE * fp = fopen( path, "r" );
      66           0 :   if( FD_UNLIKELY( !fp && errno==ENOENT ) ) return 0;
      67           0 :   else if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "error opening `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      68             : 
      69           0 :   char line[ 4096 ];
      70           0 :   while( FD_LIKELY( fgets( line, 4096, fp ) ) ) {
      71           0 :     if( FD_UNLIKELY( strlen( line ) == 4095 ) ) FD_LOG_ERR(( "line too long in `%s`", path ));
      72           0 :     if( FD_UNLIKELY( strstr( line, config->hugetlbfs.gigantic_page_mount_path ) ||
      73           0 :                       strstr( line, config->hugetlbfs.huge_page_mount_path ) ) ) {
      74           0 :       killed = 1;
      75           0 :       FD_LOG_NOTICE(( "killing process `%s` (%lu): has a workspace file descriptor open", proc_cmdline, pid ));
      76           0 :       if( FD_UNLIKELY( -1==kill( (int)pid, SIGKILL ) && errno!=ESRCH ) ) FD_LOG_ERR(( "kill failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      77           0 :       break;
      78           0 :     }
      79           0 :   }
      80           0 :   if( FD_UNLIKELY( ferror( fp ) ) )
      81           0 :     FD_LOG_ERR(( "error reading `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      82           0 :   if( FD_LIKELY( fclose( fp ) ) )
      83           0 :     FD_LOG_ERR(( "error closing `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      84             : 
      85           0 :   if( FD_UNLIKELY( killed ) ) return killed;
      86             : 
      87           0 :   FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/proc/%lu/numa_maps", pid ) );
      88           0 :   fp = fopen( path, "r" );
      89           0 :   if( FD_UNLIKELY( !fp ) ) FD_LOG_ERR(( "error opening `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      90             : 
      91           0 :   while( FD_LIKELY( fgets( line, 4096, fp ) ) ) {
      92           0 :     if( FD_UNLIKELY( strlen( line ) == 4095 ) ) FD_LOG_ERR(( "line too long in `%s`", path ));
      93           0 :     if( FD_UNLIKELY( strstr( line, "huge" ) && strstr( line, "anon" ) ) ) {
      94           0 :       killed = 1;
      95           0 :       FD_LOG_NOTICE(( "killing process `%s` (%lu): has anonymous hugepages mapped", proc_cmdline, pid ));
      96           0 :       if( FD_UNLIKELY( -1==kill( (int)pid, SIGKILL ) && errno!=ESRCH ) ) FD_LOG_ERR(( "kill failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      97           0 :       break;
      98           0 :     }
      99           0 :   }
     100           0 :   if( FD_UNLIKELY( ferror( fp ) ) )
     101           0 :     FD_LOG_ERR(( "error reading `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     102           0 :   if( FD_LIKELY( fclose( fp ) ) )
     103           0 :     FD_LOG_ERR(( "error closing `%s` (%i-%s)", path, errno, fd_io_strerror( errno ) ));
     104             : 
     105           0 :   return killed;
     106           0 : }
     107             : 
     108             : static void
     109             : wait_dead( long  started,
     110           0 :            ulong pid ) {
     111             :   /* We need to do this to prevent a race condition, since kill(SIGKILL) returns
     112             :      before the kernel actually terminates and reclaims the resources from the
     113             :      process. */
     114           0 :   while( 1 ) {
     115           0 :     int err = kill( (int)pid, 0 );
     116           0 :     if( FD_LIKELY( err==-1 && errno==ESRCH) ) return;
     117           0 :     else if( FD_LIKELY( err==-1 ) ) FD_LOG_ERR(( "kill failed (%i-%s)", errno, fd_io_strerror( errno ) ));
     118             : 
     119           0 :     if( FD_UNLIKELY( fd_log_wallclock() - started >= (long)1e9 ) )
     120           0 :       FD_LOG_ERR(( "waited too long for process to exit" ));
     121           0 :   }
     122           0 : }
     123             : 
     124             : static void
     125           0 : init( config_t * const config ) {
     126           0 :   DIR * dir = opendir( "/proc" );
     127           0 :   if( FD_UNLIKELY( !dir ) ) FD_LOG_ERR(( "error opening `/proc` (%i-%s)", errno, fd_io_strerror( errno ) ));
     128             : 
     129           0 :   ulong wait_killed_cnt = 0UL;
     130           0 :   ulong wait_killed[ 1024 ] = { 0 };
     131             : 
     132           0 :   struct dirent * entry;
     133           0 :   while(( FD_LIKELY( entry = readdir( dir ) ) )) {
     134           0 :     if( FD_UNLIKELY( entry->d_name[0] == '.' ) ) continue;
     135           0 :     char * endptr;
     136           0 :     ulong pid = strtoul( entry->d_name, &endptr, 10 );
     137           0 :     if( FD_UNLIKELY( *endptr || pid==(ulong)getpid() ) ) continue;
     138             : 
     139           0 :     int killed = maybe_kill( config, pid );
     140           0 :     if( FD_UNLIKELY( killed ) ) {
     141           0 :       if( FD_UNLIKELY( wait_killed_cnt==sizeof(wait_killed) ) ) FD_LOG_ERR(( "too many processes to kill" ));
     142           0 :       wait_killed[ wait_killed_cnt ] = pid;
     143           0 :     }
     144           0 :   }
     145             : 
     146           0 :   if( FD_UNLIKELY( -1==closedir( dir ) ) ) FD_LOG_ERR(( "closedir (%i-%s)", errno, fd_io_strerror( errno ) ));
     147             : 
     148           0 :   long started = fd_log_wallclock();
     149           0 :   for( ulong i=0; i<wait_killed_cnt; i++ ) wait_dead( started, wait_killed[ i ] );
     150           0 : }
     151             : 
     152             : static configure_result_t
     153           0 : check( config_t * const config ) {
     154           0 :   (void)config;
     155             : 
     156           0 :   PARTIALLY_CONFIGURED( "kill existing instances" );
     157           0 : }
     158             : 
     159             : configure_stage_t _kill = {
     160             :   .name            = NAME,
     161             :   .always_recreate = 1,
     162             :   .enabled         = NULL,
     163             :   .init_perm       = init_perm,
     164             :   .fini_perm       = NULL,
     165             :   .init            = init,
     166             :   .fini            = NULL,
     167             :   .check           = check,
     168             : };
     169             : 
     170             : #undef NAME

Generated by: LCOV version 1.14