LCOV - code coverage report
Current view: top level - app/firedancer/commands - adminctl_client.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 66 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 3 0.0 %

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

Generated by: LCOV version 1.14