Next: Compiling and Running Up: The Concert Tutorial Previous: More Complex Examples

Using the Emulator Debugger

This section shows some simple examples of using the debugger included in the Concert emulator (see [6] for a complete listing of the debugger functionalities).

When running a CA program using the emulator, the emulator invokes the debugger under the following four situations.

The debugger has its own debugger> prompt, as shown below.


Running the program...

User defined-break in  (FUNCTION . break) 
debugger>

Once inside the debugger, you can use the help command to display the available commands.


debugger> help

Debugger commands
object       - prints current object
goto-local   - sets current object to specified local variable
goto-param   - sets current object to specified parameter
goto-ivar    - sets current object to specified instance variable
goto-sibling - moves to a sibling
goto-array   - goes to an specified array element
local        - prints letbound vars
current      - display current executing method
parent       - prints the parent context
children     - prints all the children
up           - goes up the context tree
down         - goes down the context tree
backtrace    - lists all the predecessors of the current context
original     - go to position at which debugger was entered
blocked      - list all blocked messages
goto-blocked - goto a blocked context
unprocessed  - list all unprocessed messages
goto-message - goto an unprocessed message
waiting      - list all waiting contexts
goto-waiting - goto a waiting context
waiting-for - displays the method the current context is waiting for
continue, c  - continue execution
top-level    - go to top-level
untrace-all  - disable all tracing
trace-all    - enable tracing of all functions
exit, quit   - terminate execution & go to top-level

debugger> exit

concert>

The exit command terminates the current program and exits the debugger. To correct an error and continue execution, you can use the top-level command to return control temporarily to the emulator top level, make the corrections, and use the exit command from the top level to return to the debugger. The continue command resumes the program execution.

A Simple Example

A common error made by beginner CA programmers is omitting the reply form in a method. We show an example of using the emulator debugger to detect such an error. The program shown below, for example, does not reply from the initial_message method.


(method osystem initial_message ()
  (HELLO (global console)))

Because the initial_message method does not reply, its caller is permanently waiting for a reply. Thus, when running the program, the emulator detects a deadlock and enters the debugger.


Running the program...
HELLO 

Deadlocked with 0 blocked messages and 1 waiting contexts
debugger>

Blocked messages are method invocations trying to gain exclusive access to objects; waiting contexts are contexts waiting for replies. We can use the debugger commands current and waiting to display the current method invocation context and all method invocations that are waiting for replies, respectively.


debugger> current 
initial_message <|_osystem| {182C93FD}>

debugger> waiting

 0 ::_main <|_rootclass| {1824FC15}>

debugger> goto-waiting

Waiting method :0
_main <|_rootclass| {1824FC15}>

debugger> waiting-for

Waiting for initial_message
debugger>

As shown above, we used goto-waiting to jump to the single waiting context - an invocation of the main method, a builtin method that start the program execution and invokes initial_message. We verified that it is waiting for a reply from the initial_message method. This gives us sufficient hints to check if initial_message has a reply. We can return to the emulator prompt by the top-level command.

An Aggregate Example

In this section, we use a simple aggregate example to illustrate some more emulator commands. The following program allocates an aggregate of seven representatives and then increments the value of all representatives by 1.


(aggregate int-set value
  (parameters size)
  (initial size
           (forall i from 0 below groupsize
                   (set_value (sibling group i) i))))

(handler int-set inc ()
  (let ((old (value self)))
    (set_value self (+ 1 old))
    (OLD_VALUE (global console) old)
    (reply old)))

(handler osystem initial_message ()
  (let ((myset (new int-set 7)))
    (forall i from 0 below 7
            (inc (sibling myset i)))
    (reply STARTED)))

Running the program using the emulator produces the following output.


Running the program...
OLD_VALUE 0  
OLD_VALUE 1  
OLD_VALUE 2  
OLD_VALUE 3  
OLD_VALUE 4  
OLD_VALUE 5  
OLD_VALUE 6  
STARTED
Evaluation took:
  4.23 seconds of real time
  1.82 seconds of user run time
  0.25 seconds of system run time
  2 page faults and
  924800 bytes consed.

concert>

To check the intermediate state of objects, we can insert a (break) function in the method inc and load the modified function into the emulator at the concert> prompt.


concert> (method int-set inc ()
  (let ((old (value self)))
    (set_value self (+ 1 old))
    (break)
    (OLD_VALUE (global console) old)
    (reply old)))

Input filename: "/tmp/concert2971374993"
Reading: /tmp/concert2971374993...
...Closing: /tmp/concert2971374993
Defining method inc for  int-set

concert>

The program now encounters breakpoints when restarted using the go command.


concert> go

Building the automatic functions....
Defining method _main for  rootclass

Running the program...

User defined-break in  (FUNCTION . break) 
debugger> current
(FUNCTION . break) <|_int-set| {1036AEAD}>

debugger>

When the break function is encountered, execution suspends within the break function. As shown below, we can move to the calling frame of the break function using up. up also displays the message associated with the new context, in this case, an invocation of the inc method on a representative of the inc-set aggregate. Once we are at the parent context, local displays all the values of local variables. In our example, local shows the value of the local variable old is 0. To verify the operation of our program, we use the object command to display all instance variables of the current representative. For a representative of an aggregate, groupsize is the size of the aggregate to which the current object belongs, and myindex is the index of the current representative. We can continue the program execution via the c command.


debugger> parent
inc <|_int-set| {1036AEAD}>

debugger> up
inc <|_int-set| {1036AEAD}>

debugger> local

 old :: 0

debugger> object
group :: <AGGREGATE {1036AC8D}>
groupsize :: 7
myindex :: 0
value :: 1

debugger> c
OLD_VALUE 0  

User defined-break in  (FUNCTION . break)

We can also move to a different aggregate representative using the goto-sibling command, which prompts for an index (starts with 0). As shown below, we moved to representative 5 and 0 and displayed their instance variables. Notice that the current context does not change after the goto-sibling command.


debugger> up
inc <|_int-set| {1036B0DD}>

debugger> local

 old :: 1

debugger> object
group :: <AGGREGATE {1036AC8D}>
groupsize :: 7
myindex :: 1
value :: 1

debugger> goto-sibling

sibling number: 5

debugger> object
group :: <AGGREGATE {1036AC8D}>
groupsize :: 7
myindex :: 5
value :: 5

debugger> local

 old :: 1

debugger> goto-sibling 

sibling number: 0

debugger> object
group :: <AGGREGATE {1036AC8D}>
groupsize :: 7
myindex :: 0
value :: 1

debugger> c            
OLD_VALUE 1  

User defined-break in  (FUNCTION . break) 
...

Unexpected Emulator Response

The emulator is designed to withstand errors in user programs; however, an unanticipated error in user programs may crash the the emulator. When this happens, the emulator enters the CMU lisp debugger, as shown below.


Error in function UNIX::SIGBUS-HANDLER:  Bus Error at #x314ADC.

Restarts:
  0: [CONTINUE] Return from BREAK.

Debug  (type H for help)

(UNIX::SIGINT-HANDLER #<unavailable-arg>
                      #<unavailable-arg>
                      #.(SYSTEM:INT-SAP #xEFFFDDF8))
0]

If this does happen, you can use the command (QUIT) (notice all capitals) to abort the emulator. It is also appreciated if you mail the program that caused the crash to concert-bugs@red-herring.cs.uiuc.edu (see section 10 for using the bug reporting package).



Next: Compiling and Running Up: The Concert Tutorial


Julian Dolby
Vijay Karamcheti
John Plevyak
Xingbin Zhang
Concurrent Systems Architecture Group