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 : }