Debugging RPC Applications


Because of their distributed nature, RPC applications can be very difficult to debug. One easy way to test and debug an RPC application with, say, gdb , is to link the client and server programs without their rpcgen stubs. To do this, comment out the RPC reference in the client program. If the -C option was passed to rpcgen , then you must adjust the name of the function call appropriately (i.e., add the _svc suffix). In addition, you may need to cast the function call argument with the client reference to the correct type (i.e., struct svc_req * ). Incorporating these changes with preprocessor directives, our hello_client.c file now would be as shown in Figure 9.17.

Figure 9.17 A "debug ready" version of hello_client.c .

File : hello_client_gdb.c
 The CLIENT program: hello_client.c
 This will be the client code executed by the local client process.
 + #include 
 #include "hello.h" /* Generated by rpcgen from hello.x */
 main(int argc, char *argv[]) {
 . . . /* SAME AS LINES 9-20 in hello_client.c */
 Generate the client handle to call the server

#ifndef DEBUG

+ if ((client=clnt_create(server, DISPLAY_PRG,

DISPLAY_VER, "tcp")) == (CLIENT *) NULL) {




30 printf("client : calling function.

return_value = print_hello_1((void *) &filler, client);


printf("client : calling function.

return_value = print_hello_1_


((void *) &filler,


struct svc_req *




if (*return_value)
 printf("client : Mission accomplished
 printf("client : Unable to display message
 40 return 0;

We would compile this modified version with the command sequence shown in Figure 9.18. As none of the network libraries are referenced, the libnsl library does not need to be linked (for most versions of gcc , this is not a concern). The compiler is passed the -g flag (to generate the symbol table information for gdb ) and -DDEBUG is specified to define the DEBUG constant the preprocessor will test.

Figure 9.18 Debugging the clientserver application with gdb .

linux$ gcc -DDEBUG -g hello_client_gdb.c hello_server.c

<-- 1

linux$ gdb -q a.out
(gdb) list 25,35
25 if ((client=clnt_create(server, DISPLAY_PRG,
26 DISPLAY_VER, "tcp")) == (CLIENT *) NULL) {
27 clnt_pcreateerror(server);
28 exit(2);
29 }
30 printf("client : calling function.
31 return_value = print_hello_1((void *) &filler, client);
32 #else
33 printf("client : calling function.
34 return_value=print_hello_1_svc((void *) &filler,(struct svc_req *)client);
35 #endif

(gdb) break 34

<-- 2

Breakpoint 1 at 0x804853f: file hello_client_gdb.c, line 34.

(gdb) run kahuna
Starting program: /home/faculty/gray/revision/09/hello_files/a.out kahuna
client : calling function.

Breakpoint 1, main (argc=2, argv=0xbffffc34) at hello_client_gdb.c:34
34 return_value=print_hello_1_svc((void *)&filler,(struct svc_req *)client);

(gdb) step

<-- 3

print_hello_1_svc (filler=0xbffffbbc, req=0x80497ec) at hello_server.c:10
10 ok = printf("server : Hello, world.

(gdb) list

<-- 4

5 #include 
6 #include "hello.h" /* is generated by rpcgen from hello.x */
7 int *
8 print_hello_1_svc(void * filler, struct svc_req * req) {
9 static int ok;
10 ok = printf("server : Hello, world.
11 return (&ok);
12 }

(gdb) quit
The program is running. Exit anyway? (y or n) y

(1) Compile with gcc . Define the DEBUG constant and generate the symbol table information.

(2) Set a break point at line 34 in the client program.

(3) Step into what was formerly the remote procedure.

(4) This is now the code for the server.

Programs and Processes

Processing Environment

Using Processes

Primitive Communications


Message Queues


Shared Memory

Remote Procedure Calls



Appendix A. Using Linux Manual Pages

Appendix B. UNIX Error Messages

Appendix C. RPC Syntax Diagrams

Appendix D. Profiling Programs

Interprocess Communication in Linux
Interprocess Communications in Linux: The Nooks and Crannies
ISBN: 0130460427
EAN: 2147483647
Year: 2001
Pages: 136 © 2008-2020.
If you may any questions please contact us: