Debugging With RDi and Service Entry Points
IBM i experts Jon Paris and Susan Gantner explain debugging procedures for Rational Developer for i.
The last time we wrote about the RDi debugger was a long time ago—so long ago that the product we now know as RDi (Rational Developer for IBM i) has been renamed three times in the intervening years! Fortunately, the current name seems to have stuck for quite a while. And even more fortunately, RDi keeps getting better and the pace of useful enhancements has become faster in recent years.
Since the RDi debugger still seems to be a popular topic among RPGers, we've decided to revisit the topic here. There are a couple of recent enhancements we'll cover here but our primary mission is to help with getting started using the RDi debugger.
Starting an RDi Debug SessionThe part of debugging with RDi that seems most baffling to many people is how to start a debug session. There are two primary ways to get a debug session started:
- Creating and using a debug configuration
- Using a Service Entry Point
Before we get started on this topic, it's good to know that there are preferences that you can set—at least one that you probably should check out before using SEPs.
Open RDi Preferences and type “debug” into the filter box near the top of the left-hand panel. In the filtered list, select IBM i Debug. The entry that most people need to change here is "Update production files." Most IBM i shops we work with need to turn that preference on (it’s set off by default). Choose whatever setting you normally need when debugging in the green screen for the same parameter. Now that we've got that set, let's get started debugging with SEPs.
What Is a Debug Service Entry Point?It’s a simple way to get control of a running program for debug purposes. A debug SEP is a monitor of sorts on IBM i that will watch for a combination of a specific program (or procedure) starting to run anywhere on the system by a specific user profile. Whenever the combination of program and user is found, the system stops the program execution on the first line of code, then does what is the rough equivalent of STRSRVJOB (Start Service Job) and STRDBG (Start Debug) on the job and program. Then it notifies the developer who set the the SEP that the program is ready to debug.
Steps to Start an SEP Debug Session
1.Select the program to debugIn Remote Systems (or Object Table), right click on the program you want to debug—or at least the first one in the call stack. You can add more programs to the session later if you need to. From the context menu, choose "Debug or Code Coverage (Service Entry)." You can do this on either the source member or the *PGM or *SRVPGM object. We prefer to use objects to ensure we're debugging exactly the code we want.
2.Confirm the SEP settingsIt may take a few seconds for the SEP to be set. When it is, it will appear in a Service Entry Points view (typically just underneath your editor). From there you can confirm that the defaults for the SEP are what you need. It selects all the procedures and modules in the program and it uses your own user profile, i.e., the one you are using with your RDi connection. If the program to be debugged will be run under a different user profile, you must modify the user ID here. Make sure to confirm that the debug mode is selected (via the bug icon as shown in Figure 1 near the top right). The alternative mode (the icon to the right of the bug) is for Code Coverage. Code Coverage is a different tool that also uses SEPs, so make sure you have the correct mode set for debugging. Any changes you need to make to the default selections can be made from the context menu for the entry in the SEP list.
3. Run the code to be debuggedThis is where SEPs shine because it doesn't matter how you run the program nor whether the program you're debugging runs in an interactive (green screen) job or if it is submitted to batch or even if it runs in a server-type job. Whenever and wherever the user ID specified starts to run the program specified the system will detect it and start the debug session in your RDi workbench. If the debug perspective isn't already open, it will open it. You may be prompted the first time to ask if you want to switch perspective. It will also open the source or listing view for the code (depending on the option you specified at compile time) in the edit window. It will look something like what's shown in Figure 2 below. You're now ready to debug your code.
New feature: Before going on to talk about what you can do in the debug session itself, in the image above you can see the first of the more recent debugger enhancements. Note the column for "Condition" in the SEP view. This is new for RDi 22.214.171.124—you may specify a condition, which will be tested as the program starts up. For example, the SEP could be conditional on a specific value of a parameter coming into the program.
In the image above, you can see that I have already set a couple of breakpoints at statements 136 and 141. Breakpoints can be set (or removed) by double clicking to the left of the statement number or from the context menu in the editor. Breakpoints can also be disabled without removing them. There is a Breakpoints view in the upper right section of the debug perspective (not in the foreground in figure 2.) From there you can see all your breakpoints and manage them - remove them, disable them or edit them.
To make a breakpoint conditional, edit it via the context menu (from either the editor or the Breakpoints view). The condition entry field is on the second panel of the edit dialog. Watch breakpoints are not associated with any specific line of code but will stop whenever the value of a specific variable changes. They can also be set and managed from the Breakpoints view.
One especially useful feature of RDi breakpoints is that they are remembered even after the current debug session is ended. If you weren't able to find the bug during a session, you can come back hours or days later and the breakpoints will still be there ready to try again. Because of this, it's helpful to know that you can quickly clear all your breakpoints at once from the Breakpoints view in case you forgot to clear them after your last debug session for a different problem. Remove all breakpoints from the context menu or click on the double X icon. If you think you may need them again, you could disable them.
One last breakpoint option isn't technically a breakpoint. Right click on a line of code and choose "Run to Location" to do what is effectively a temporary one-time-only breakpoint.
Can I Step Through My Code?There are four different types of debug stepping available in RDi. The two options available in the host-based (green screen) debugger are there: Step Over (F10 in green screen, F5 in RDi) and Step Into (F22 in green screen, F6 in RDi.) You can use them from the icons (the two in the middle highlighted in Figure 3) as well as from the shortcut keys or use the step options from the Run menu.
The rightmost of the step icons in Figure 3 is the Step Return option. When you have stepped into a program or procedure and subsequently decide you don't want to step through all the code, you can use Step Return to return to the caller and stop at the next line of code. This feature only works when the code you stepped into is an ILE language. I.e., it will work if you stepped into an RPGLE, CBLLE or CLLE program or procedure but not if you stepped into a CLP or RPG program. In those cases, of course, you can switch back to the caller in the editor and set a breakpoint at the next line of code after the call, then let the code run to that break point by using the green Resume button showing in Figure 3 to the left fo the step buttons or by using F8 or the Resume option from the Run menu.
The first of the four step icons highlighted above can be very useful when you aren't familiar enough with the flow of the code to even know where to set your breakpoints. It's an Animated Step Into. It will automatically perform step into actions while you sit back and watch what happens. The speed of the stepping can be controlled using the arrow next to the icon. This is especially helpful if you have set up some variable values to be monitored, which we're just about to cover.
What About Variable Values?
When debugging you often need to know what the current values are for some specific variables. The RDi debug perspective lets you look at and/or change the values of variables in a few ways.
For a quick peek at a value the simplest way is to hover over the variable name in the editor. The current value will be shown when in an active debug session. You also have a Variables view in the top right quadrant of the debug perspective (a tab in the same area where we saw the Breakpoints view before). This shows the current values of all the variables in the active program/procedure. This works well for very small pieces of code, but it can cause the debugger to operate very slowly for very large programs, such as many older RPG and COBOL programs because of the time it takes to populate hundreds or thousands of values at every breakpoint or step. Therefore when debugging larger programs, we recommend that you don't leave the Variables view in the foreground. Read on for our favorite choice for the foreground.
What should you put in the foreground while debugging? We typically like to bring the Monitors view forward. Monitors allows you to keep an eye on the values of a few specific variables of your own choosing every time the code stops at a breakpoint or step. Not only does it give you a quick way to see the values of the variables you're most interested in, it also highlights in red any values that changed since the list time the program was stopped. This is illustrated in the image below.
In the Monitors view you can also change the value of a monitored variable; double click on the value to make an entry box appear.
New feature: The second new feature in the RDi debugger is related to looking at variable values. As of RDi 126.96.36.199, longer variable values can be viewed while debugging. The earlier size limitation of 4096 could be problematic when dealing with large variables holding things such as XML or JSON documents.
Limitations of SEPs
We mentioned earlier that there are some cases where you can't use SEPs.
The program that you're using to start the debug session via SEP must be an ILE language program, such as RPGLE, CBLLE, CLLE. Once an SEP debug session is started, you can debug any program, including RPG, CLP and CBL. It's only the program that kicks off the debug session that must be ILE. One workaround that we've seen used when there's an RPG or CLP program you want to debug is to create a simple CLLE program that does nothing more than call the RPG or CLP. Start the SEP from the CLLE program and then step into the RPG or CLP and/or any other programs you may need to include.
Another limitation is that the instance of the program that you want to debug cannot already be running. For example, if the program to be debugged is a never-ending-program or if it is running but stopped, perhaps due to an error or a green screen display. The SEP must be able to get control of the program at the time it first starts.
You can still use the RDi debugger in those situations - you just can't use SEPs to begin the process.
It's important to remember that the use of SEPs is only to get the debug session started. After the session is started, the use of breakpoints, stepping and viewing, changing or monitoring variable values is the same, whether you used an SEP to get there or a debug configuration.
We don't have the space here to cover the use of debug configurations. But we'll cover that along with a few other details about using the RDi debugger in a later article.
In the meantime, if you want to take a look at a short video Susan created about how to get an RDi debug session started, take a look at this one.