@@ -220,22 +220,29 @@ def print_info(self, terminal):
220220 print (terminal .print_type_tag ('rb_control_frame_t' , int (self .cfp ), None ))
221221
222222
223- class RubyFiberScanHeapCommand ( debugger . Command ) :
223+ class RubyFiberScanHeapHandler :
224224 """Scan heap and list all Ruby fibers."""
225225
226+ USAGE = command .Usage (
227+ summary = "Scan heap and list all Ruby fibers" ,
228+ parameters = [],
229+ options = {
230+ 'limit' : (int , None , 'Maximum fibers to find' ),
231+ 'cache' : (str , None , 'Cache file to use (default: fibers.json)' )
232+ },
233+ flags = [
234+ ('terminated' , 'Include terminated fibers in results' )
235+ ],
236+ examples = [
237+ ("rb-fiber-scan-heap" , "Find all non-terminated fibers" ),
238+ ("rb-fiber-scan-heap --limit 10" , "Find first 10 fibers" ),
239+ ("rb-fiber-scan-heap --terminated" , "Include terminated fibers" ),
240+ ("rb-fiber-scan-heap --cache my.json" , "Use custom cache file" )
241+ ]
242+ )
243+
226244 def __init__ (self ):
227- super (RubyFiberScanHeapCommand , self ).__init__ ("rb-fiber-scan-heap" , debugger .COMMAND_USER )
228245 self .heap = heap .RubyHeap ()
229-
230- def usage (self ):
231- """Print usage information."""
232- print ("Usage: rb-fiber-scan-heap [--limit N] [--cache [filename]] [--terminated]" )
233- print ("Examples:" )
234- print (" rb-fiber-scan-heap # Find all non-terminated fibers" )
235- print (" rb-fiber-scan-heap --limit 10 # Find first 10 non-terminated fibers" )
236- print (" rb-fiber-scan-heap --terminated # Include terminated fibers" )
237- print (" rb-fiber-scan-heap --cache # Use fibers.json cache" )
238- print (" rb-fiber-scan-heap --cache my.json # Use custom cache file" )
239246
240247 def save_cache (self , fiber_values , filename ):
241248 """Save fiber VALUE addresses to cache file.
@@ -474,29 +481,21 @@ def _print_fiber_info(self, terminal, index, fiber_obj):
474481 print ()
475482
476483
477- class RubyFiberScanSwitchCommand ( debugger . Command ) :
478- """Switch to a fiber from the scan heap cache.
484+ class RubyFiberScanSwitchHandler :
485+ """Switch to a fiber from the scan heap cache."""
479486
480- Usage: rb-fiber-scan-switch <index>
481- Example: rb-fiber-scan-switch 0
482- rb-fiber-scan-switch 2
483-
484- Note: This command requires a fiber cache populated by 'rb-fiber-scan-heap'.
485- """
487+ USAGE = command .Usage (
488+ summary = "Switch to a fiber from scan cache by index" ,
489+ parameters = [('index' , 'Fiber index from rb-fiber-scan-heap' )],
490+ options = {},
491+ flags = [],
492+ examples = [
493+ ("rb-fiber-scan-switch 0" , "Switch to first fiber" ),
494+ ("rb-fiber-scan-switch 2" , "Switch to third fiber" )
495+ ]
496+ )
486497
487- def __init__ (self ):
488- super (RubyFiberScanSwitchCommand , self ).__init__ ("rb-fiber-scan-switch" , debugger .COMMAND_USER )
489-
490- def usage (self ):
491- """Print usage information."""
492- print ("Usage: rb-fiber-scan-switch <index>" )
493- print ("Examples:" )
494- print (" rb-fiber-scan-switch 0 # Switch to fiber #0" )
495- print (" rb-fiber-scan-switch 2 # Switch to fiber #2" )
496- print ()
497- print ("Note: Run 'rb-fiber-scan-heap' first to populate the fiber cache." )
498-
499- def invoke (self , arg , from_tty ):
498+ def invoke (self , arguments , terminal ):
500499 global _fiber_cache
501500
502501 if not arg or not arg .strip ():
@@ -650,42 +649,25 @@ def deactivate(self):
650649 gdb .invalidate_cached_frames ()
651650
652651
653- class RubyFiberSwitchCommand (debugger .Command ):
654- """Switch debugger's stack view to a specific fiber.
655-
656- Usage: rb-fiber-switch <fiber_value_or_address>
657- rb-fiber-switch off
658-
659- Examples:
660- rb-fiber-switch 0x7fffdc409ca8 # VALUE address
661- rb-fiber-switch $fiber_val # Debugger variable
662- rb-fiber-switch off # Deactivate unwinder (GDB only)
652+ class RubyFiberSwitchHandler :
653+ """Switch debugger's stack view to a specific fiber."""
663654
664- This uses a custom unwinder (GDB only) to make the debugger follow the fiber's saved
665- stack, allowing you to use 'bt', 'up', 'down', 'frame', etc.
666- Works even with core dumps!
667-
668- Based on technique from Facebook Folly fibers.
669- """
655+ USAGE = command .Usage (
656+ summary = "Switch debugger stack view to a specific fiber" ,
657+ parameters = [('fiber' , 'Fiber VALUE/address or "off" to deactivate' )],
658+ options = {},
659+ flags = [],
660+ examples = [
661+ ("rb-fiber-switch 0x7fffdc409ca8" , "Switch to fiber at address" ),
662+ ("rb-fiber-switch $fiber" , "Switch using debugger variable" ),
663+ ("rb-fiber-switch off" , "Deactivate unwinder (GDB only)" )
664+ ]
665+ )
670666
671667 def __init__ (self ):
672- super (RubyFiberSwitchCommand , self ).__init__ ("rb-fiber-switch" , debugger .COMMAND_USER )
673668 if debugger .DEBUGGER_NAME == 'gdb' :
674669 self ._ensure_unwinder ()
675670
676- def usage (self ):
677- """Print usage information."""
678- print ("Usage: rb-fiber-switch <fiber_value_or_address>" )
679- print (" rb-fiber-switch off" )
680- print ("Examples:" )
681- print (" rb-fiber-switch 0x7fffdc409ca8 # VALUE address" )
682- print (" rb-fiber-switch $fiber # Debugger variable" )
683- print (" rb-fiber-switch off # Deactivate unwinder (GDB only)" )
684- print ()
685- print ("After switching, you can use: bt, up, down, frame, info locals, etc." )
686- if debugger .DEBUGGER_NAME != 'gdb' :
687- print ("Note: Stack unwinding is only supported in GDB" )
688-
689671 def _ensure_unwinder (self ):
690672 """Ensure the fiber unwinder is registered (GDB only)."""
691673 global _fiber_unwinder
@@ -840,26 +822,20 @@ def invoke(self, arg, from_tty):
840822 print (" rb-fiber-switch off" )
841823
842824
843- class RubyFiberScanStackTraceAllCommand (debugger .Command ):
844- """Print stack traces for all fibers in the scan cache.
845-
846- Usage: rb-fiber-scan-stack-trace-all
825+ class RubyFiberScanStackTraceAllHandler :
826+ """Print stack traces for all fibers in the scan cache."""
847827
848- This command prints the Ruby stack trace for each fiber that was
849- found by 'rb-fiber-scan-heap'. Run that command first to populate
850- the fiber cache.
851- """
828+ USAGE = command .Usage (
829+ summary = "Print stack traces for all cached fibers" ,
830+ parameters = [],
831+ options = {},
832+ flags = [],
833+ examples = [
834+ ("rb-fiber-scan-heap; rb-fiber-scan-stack-trace-all" , "Scan fibers then show all backtraces" )
835+ ]
836+ )
852837
853- def __init__ (self ):
854- super (RubyFiberScanStackTraceAllCommand , self ).__init__ ("rb-fiber-scan-stack-trace-all" , debugger .COMMAND_USER )
855-
856- def usage (self ):
857- """Print usage information."""
858- print ("Usage: rb-fiber-scan-stack-trace-all" )
859- print ()
860- print ("Note: Run 'rb-fiber-scan-heap' first to populate the fiber cache." )
861-
862- def invoke (self , arg , from_tty ):
838+ def invoke (self , arguments , terminal ):
863839 global _fiber_cache
864840
865841 # Check if cache is populated
@@ -895,7 +871,7 @@ def invoke(self, arg, from_tty):
895871
896872
897873# Register commands
898- RubyFiberScanHeapCommand ( )
899- RubyFiberScanSwitchCommand ( )
900- RubyFiberSwitchCommand ( )
901- RubyFiberScanStackTraceAllCommand ( )
874+ debugger . register ( "rb-fiber-scan-heap" , RubyFiberScanHeapHandler , usage = RubyFiberScanHeapHandler . USAGE )
875+ debugger . register ( "rb-fiber-scan-switch" , RubyFiberScanSwitchHandler , usage = RubyFiberScanSwitchHandler . USAGE )
876+ debugger . register ( "rb-fiber-switch" , RubyFiberSwitchHandler , usage = RubyFiberSwitchHandler . USAGE )
877+ debugger . register ( "rb-fiber-scan-stack-trace-all" , RubyFiberScanStackTraceAllHandler , usage = RubyFiberScanStackTraceAllHandler . USAGE )
0 commit comments