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

Generated by: LCOV version 1.14