LCOV - code coverage report
Current view: top level - app/firedancer/commands - adminctl_client.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 65 0.0 %
Date: 2026-08-14 04:54:57 Functions: 0 3 0.0 %

          Line data    Source code
       1             : #define _GNU_SOURCE
       2             : #include "adminctl_client.h"
       3             : 
       4             : #include "../../shared/fd_bootinfo.h"
       5             : #include "../../../disco/topo/fd_topo.h"
       6             : #include "../../../util/pod/fd_pod.h"
       7             : #include "../../../util/fd_version.h"
       8             : 
       9             : #include <errno.h>
      10             : #include <fcntl.h>
      11             : #include <string.h>
      12             : #include <sys/mman.h>
      13             : #include <sys/stat.h>
      14             : #include <unistd.h>
      15             : 
      16             : static fd_adminctl_t *
      17           0 : attach_from_config( config_t * config ) {
      18           0 :   ulong admin_ctl_obj_id = fd_pod_query_ulong( config->topo.props, "adminctl", ULONG_MAX );
      19           0 :   if( FD_UNLIKELY( admin_ctl_obj_id==ULONG_MAX ) ) FD_LOG_ERR(( "The command could not communicate with the running Firedancer process. "
      20           0 :                                                                 "It is possible you are running the command from an older or newer "
      21           0 :                                                                 "version of Firedancer that is no longer compatible." ));
      22             : 
      23           0 :   fd_topo_obj_t const * admin_ctl_obj = &config->topo.objs[ admin_ctl_obj_id ];
      24             : 
      25           0 :   fd_topo_join_workspace( &config->topo, &config->topo.workspaces[ admin_ctl_obj->wksp_id ], FD_SHMEM_JOIN_MODE_READ_WRITE, FD_TOPO_CORE_DUMP_LEVEL_DISABLED );
      26             : 
      27           0 :   fd_adminctl_t * adminctl = fd_adminctl_join( fd_topo_obj_laddr( &config->topo, admin_ctl_obj->id ) );
      28           0 :   if( FD_UNLIKELY( !adminctl ) ) FD_LOG_ERR(( "The command could not communicate with the running Firedancer process. "
      29           0 :                                               "It is possible you are running the command from an older or newer "
      30           0 :                                               "version of Firedancer that is no longer compatible." ));
      31           0 :   return adminctl;
      32           0 : }
      33             : 
      34             : static fd_adminctl_t *
      35           0 : attach_from_bootinfo( fd_bootinfo_instance_t const * instance ) {
      36           0 :   fd_bootinfo_t const * info = &instance->info;
      37             : 
      38           0 :   if( FD_UNLIKELY( !info->adminctl_wksp_file[ 0 ] ) )
      39           0 :     FD_LOG_ERR(( "The running validator `%s` does not support being administered by this command.", info->name ));
      40             : 
      41           0 :   fd_bootinfo_notice( instance );
      42             : 
      43           0 :   if( FD_UNLIKELY( strcmp( info->commit_ref, fd_commit_ref_cstr ) ) )
      44           0 :     FD_LOG_INFO(( "running validator is commit %s, this binary is commit %s", info->commit_ref, fd_commit_ref_cstr ));
      45             : 
      46           0 :   char path[ PATH_MAX ];
      47           0 :   FD_TEST( fd_cstr_printf_check( path, sizeof(path), NULL, "%s/.%s/%s", instance->mount_path, fd_shmem_page_sz_to_cstr( info->adminctl_page_sz ), info->adminctl_wksp_file ) );
      48             : 
      49           0 :   int fd = open( path, O_RDWR );
      50           0 :   if( FD_UNLIKELY( -1==fd ) ) FD_LOG_ERR(( "open(%s) failed (%i-%s).  The validator `%s` appears to be running but its "
      51           0 :                                            "shared memory could not be opened.", path, errno, fd_io_strerror( errno ), info->name ));
      52             : 
      53           0 :   struct stat st;
      54           0 :   if( FD_UNLIKELY( -1==fstat( fd, &st ) ) ) FD_LOG_ERR(( "fstat(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      55           0 :   if( FD_UNLIKELY( info->adminctl_offset+fd_adminctl_footprint()>(ulong)st.st_size ) )
      56           0 :     FD_LOG_ERR(( "The validator `%s` published an invalid control region descriptor.  It is possible you are "
      57           0 :                  "running the command from an older or newer version of Firedancer that is no longer compatible.", info->name ));
      58             : 
      59           0 :   void * base = mmap( NULL, (ulong)st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );
      60           0 :   if( FD_UNLIKELY( base==MAP_FAILED ) ) FD_LOG_ERR(( "mmap(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
      61           0 :   if( FD_UNLIKELY( close( fd ) ) ) FD_LOG_WARNING(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
      62             : 
      63           0 :   fd_adminctl_t * adminctl = fd_adminctl_join( (uchar *)base+info->adminctl_offset );
      64           0 :   if( FD_UNLIKELY( !adminctl ) ) FD_LOG_ERR(( "The command could not communicate with the running Firedancer process. "
      65           0 :                                               "It is possible you are running the command from an older or newer "
      66           0 :                                               "version of Firedancer that is no longer compatible." ));
      67           0 :   return adminctl;
      68           0 : }
      69             : 
      70             : fd_adminctl_t *
      71             : adminctl_client_attach( config_t *   config,
      72           0 :                         char const * opt_name ) {
      73           0 :   if( FD_LIKELY( config->has_user_config ) ) return attach_from_config( config );
      74             : 
      75           0 :   fd_bootinfo_instance_t instances[ FD_BOOTINFO_INSTANCE_MAX ];
      76           0 :   ulong cnt = fd_bootinfo_discover( instances, FD_BOOTINFO_INSTANCE_MAX );
      77             : 
      78           0 :   fd_bootinfo_instance_t * match     = NULL;
      79           0 :   ulong                    match_cnt = 0UL;
      80           0 :   ulong                    stale_cnt = 0UL;
      81           0 :   for( ulong i=0UL; i<cnt; i++ ) {
      82           0 :     if( FD_UNLIKELY( opt_name && opt_name[ 0 ] && strcmp( instances[ i ].info.name, opt_name ) ) ) continue;
      83           0 :     if( FD_UNLIKELY( !instances[ i ].live ) ) { stale_cnt++; continue; }
      84           0 :     match = &instances[ i ];
      85           0 :     match_cnt++;
      86           0 :   }
      87             : 
      88           0 :   if( FD_UNLIKELY( !match_cnt ) ) {
      89           0 :     if( FD_UNLIKELY( cnt ) ) fd_bootinfo_print( instances, cnt );
      90           0 :     if( FD_UNLIKELY( stale_cnt ) ) FD_LOG_ERR(( "No running validator found, but %lu stopped validator(s) left shared memory "
      91           0 :                                                 "behind.  Start the validator, or pass --config to attach explicitly.", stale_cnt ));
      92           0 :     FD_LOG_ERR(( "No running validator found.  If a validator is running, pass --config with the "
      93           0 :                  "configuration file it was started with." ));
      94           0 :   }
      95             : 
      96           0 :   if( FD_UNLIKELY( match_cnt>1UL ) ) {
      97           0 :     fd_bootinfo_print( instances, cnt );
      98           0 :     FD_LOG_ERR(( "Multiple running validators found.  Pass --name to select one." ));
      99           0 :   }
     100             : 
     101           0 :   return attach_from_bootinfo( match );
     102           0 : }

Generated by: LCOV version 1.14