File Coverage

lib/Devel/Debug/Server.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1 2     2   22 use strict;
  2         5  
  2         65  
2 2     2   9 use warnings;
  2         3  
  2         65  
3             package Devel::Debug::Server;
4              
5 2     2   1308 use ZeroMQ qw/:all/;
  0            
  0            
6             use Time::HiRes qw(usleep nanosleep);
7             use Storable;
8              
9             my $NO_COMMAND = 'no_command';
10             our $READY_COMMAND = 'ready_command';
11             our $RUN_COMMAND = 'r';
12             our $STEP_COMMAND = 's';
13             our $WAIT_COMMAND = 'WAIT_CMD';
14             our $SET_BREAKPOINT_COMMAND = 'b';
15             our $REMOVE_BREAKPOINT_COMMAND = 'remove_command';
16             our $RETURN_COMMAND = 'return';
17             our $EVAL_COMMAND = 'e';
18             our $SUSPEND_COMMAND = 'suspend';
19              
20             our $DEBUG_PROCESS_TYPE = 'DEBUG_PROCESS';
21             our $DEBUG_GUI_TYPE = 'DEBUG_GUI';
22             our $DEBUG_BREAKPOINT_TYPE = 'DEBUG_BREAKPOINT_GUI';
23              
24             my $requester = undef;
25              
26             # ABSTRACT: communication module for debuging processes
27              
28              
29             sub initZeroMQ{
30             if (!defined $requester){
31             my $cxt = ZeroMQ::Context->new;
32             $requester = $cxt->socket(ZeroMQ::Constants::ZMQ_REQ);
33             $requester->connect("tcp://127.0.0.1:5000");
34             }
35             }
36              
37              
38             sub send {
39             my($data) = @_;
40              
41             my $programInfoStr = Storable::freeze($data);
42             $requester->send($programInfoStr);
43              
44             my $reply = $requester->recv()->data();
45             return Storable::thaw($reply);
46             }
47              
48              
49             1;
50              
51             =pod
52              
53             =head1 NAME
54              
55             Devel::Debug::Server - communication module for debuging processes
56              
57             =head1 VERSION
58              
59             version 1.001
60              
61             =head1 SYNOPSIS
62              
63             #on command-line
64            
65             #... first launch the debug server (only once)
66            
67             tom@house:debugServer.pl
68            
69             server is started...
70            
71             #now launch your script(s) to debug
72            
73             tom@house:debugAgent.pl path/to/scriptToDebug.pl
74            
75             #in case you have arguments
76            
77             tom@house:debugAgent.pl path/to/scriptToDebug.pl arg1 arg2 ...
78            
79             #now you can send debug commands with the Devel::Debug::Server::Client module
80             #in your debuggerGUI.pl...
81             $debugData = Devel::Debug::Server::Client::refreshData(); #$debugData contains all debugging processes infos
82            
83             #get the debug infos for process $processToDebugPID
84             $processInfos = $debugData->{processesInfo}{$processToDebugPID};
85            
86             #check if process is halted
87             if($processInfos->{halted} == 1){
88             print("process is halted.\n");
89             }
90            
91             #check if process is finished
92            
93             if($processInfos->{finished} == 1){
94             print("process is finished.\n");
95             }
96            
97             #set a breakpoint on line 9
98             Devel::Debug::Server::Client::breakPoint($pathToPerlFile,9);
99             #remove breakpoint line 14
100             Devel::Debug::Server::Client::removeBreakPoint($scriptPath,14);
101            
102             #now run the process
103             Devel::Debug::Server::Client::run($processToDebugPID)
104            
105             #return from current subroutine
106             Devel::Debug::Server::Client::return($processToDebugPID);
107            
108             #eval an expression in the process context
109             Devel::Debug::Server::Client::eval($processToDebugPID,'$variable = 0');
110            
111             #now time to do one step
112             Devel::Debug::Server::Client::step($processToDebugPID);
113            
114             #suspend a running process
115             Devel::Debug::Server::Client::suspend($processToDebug);
116              
117             =head1 DESCRIPTION
118              
119             This module provide a server for debugging multiples perl processes.
120              
121             Lots of debugging modules a available for perl (graphical and non graphical), their are all directly attached to the debugged script.
122             This implies the following limitation :
123             - it is not easy to debug multiple processes (10 processes implies 10 debugging shell windows)
124             - it is not easy to debug forking processes
125             - it is not easy to automate breakpoints. breakpoints should be set again at each script execution (and automation is not trivial)
126              
127             This module aims at providing an debugging engine so that we can provide a debugger equivalent the jvm one where you can observe and halt each jvm thread as you want but working with perl processes instead of jvm threads. Every debugging processes connect to the debugging server providing runtime informations and receiving breakpoint list to set.
128              
129             This module aims at providing a convenient base be to develop one or more GUI client to control this debug server.
130              
131             Currently there are no GUI clients available.
132              
133             One can launch one server and debug as many processes as he wants :
134             - all debugging informations are centralized by the server
135             - all debugging commands are sent by the server when it receives a client request
136              
137             For example, the tests script "01-debug-script.t" launch a debug server and 3 processes. All processes are being debugged at the same time (breakpoints are set for all processes).
138              
139             =head1 Architecture
140              
141             There is one client process that send commands and retrieve data from the server process ; the tests scripts are client processes.
142             Server process receives messages from the processes to debug and gives them commands. The server can also send signal in order to check if a process is alive or to halt it (like ctrl+C on perl debugger).
143             The processes to debug register automatically to the server on startup and wait for command (at least the run command).
144             All communications are managed using simple messages on localhost:5000 (zeroMq library).
145              
146             ------------------ ZMQ ---------------- ZMQ --------------------
147             | client process | ----> |server process|<-------|process to debug 1|
148             ------------------ | (port 5000) | --------------------
149             ----------------
150             ^ ZMQ --------------------
151             -------|process to debug 2|
152             --------------------
153              
154             =head1 Asynchrounous design
155              
156             All communications between all component are asynchronous in order nobody waits for a dead process.
157             This means all command are sent without waiting the result.
158              
159             For example :
160             - client process sends a "eval" command to the server and server aknowledges the message
161             - then server is waiting for the target process to request some new commands to send the "eval" (updating its informations the same way)
162             - process to debug execute the "eval" command and generates a new request to the server to update the "lastEvalResult" for this PID in server process memory
163             - next time client process will call "refreshData", it will get the process informations with "eval" command result.
164              
165             As a conclusion, client process need to regular call "refreshData" to maintain usefull information on screen.
166              
167             =head1 Limitations :
168              
169             Works only for linux systems (should be possible to make it works for windows)
170             No GUI client available today.
171             It doesn't manage for now forking processes.
172             It doesn't manage threads.
173              
174             =head1 SEE ALSO
175              
176             L
177              
178             L
179              
180             L
181              
182             =head1 AUTHOR
183              
184             Jean-Christian HASSLER
185              
186             =head1 COPYRIGHT AND LICENSE
187              
188             This software is copyright (c) 2012 by Jean-Christian HASSLER.
189              
190             This is free software; you can redistribute it and/or modify it under
191             the same terms as the Perl 5 programming language system itself.
192              
193             =cut
194              
195             __END__