LCOV - code coverage report
Current view: top level - app/shared_dev/commands/configure - kill.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 107 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 6 0.0 %

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

Generated by: LCOV version 1.14