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