"Linux Gazette...making Linux just a little more fun!"

Debugging CGI Programs over TCP Sockets

by Kevin O'Malley


This article evolved from my frustration in developing and debugging CGI programs written for the AuctionBot, a multi-purpose auction server. I found that the available C libraries, C++ class libraries and web server extensions did not fit my needs so I decided to implement a different approach based on debugging over TCP sockets. Using this approach, I have successfully implemented and debugged most of the CGI's for this project.

My development machine at work is a Sun Ultra 1 running Solaris 2.5. At home I have a Linux box running RedHat 5.0. I developed all my debugging code under Linux. Linux provides a very stable development environment that allowed me to develop, test and experiment locally, without requiring remote login to the Sun. Once the code was running, I simply moved it over to the Sun, built it and started using it.


Debugging CGI (Common Gateway Interface) programs present unique challenges not found when debugging programs in more traditional environments. CGI's are executed by a web server and run within the environment created by the web server. This makes a CGI's runtime behavior strongly coupled to the environment setup by the web server. A developer can not simply run a CGI from a shell, or under a debugger, and expect it to behave as it does while running within the web server environment.

A common CGI debugging technique involves capturing the environment that a CGI is run under (usually to a disk file), restoring the environment on a local machine and running the CGI locally within the restored environment. Using this technique, CGI's can be run from the command-line, or from within a debugger (gdb for example) and debugged using familiar debugging techniques. This technique is straight forward, but requires the developer to perform the extra work of capturing and restoring the CGI runtime environment.

Another problem in debugging CGI's is viewing the output of a CGI that fails to run correctly. If you are using Apache 1.2 or later, this can be addressed by configuring the web server to log error messages to a error log file. This approach works for some classes of problems, but does not provide the granularity I wanted.

One could write debugging/status information to log files and use tail -f logfile to view the file. This works, but can produce deadlock conditions if multiple copies of your CGI are running and they attempt to use the same shared resource (the log file) and do not use file locking. Developers must provide file locking code and handle possible deadlock conditions, including cases where a CGI crashes before it releases its file lock [1]. In addition, all writes must be atomic to ensure correct output.

Ideally, one would like to debug the CGI in its natural surroundings, i.e. from within environment created by the web server, without any extra setup work.


An alternative technique is to use network sockets to write debugging information using printf-like statements to a debug server application running on the developers local machine, or any machine on the network. Using this technique, CGI's can be debugged and monitored quickly and easily while running within the server environment. The class SocketDB provides the required behavior to debug CGI's over TCP sockets. The class supplies methods to connect to the server and write strings over a TCP socket.
class SocketDB
  int mSD;
  ErrorTypes mErrorType;
  int mConnected;
  SocketDB(char *name, int port);

  int Connected() { return mConnected; }      
  int ErorType() { return mErrorType; }      
  int Connect(char *name, int port);
  int Print(char *format,...);
  int Println(char *format,...);
To connect to the server use the SocketDB constructor passing the server name and port, or use the Connect method. Both will attempt to connect to the server on the specified port. Use the Connected method to determine if the connection was successful or you can use the return value of Connect. The Connect method returns 1 if connected, otherwise, 0. If a connect error occurs, use the ErorType method to get error information. The file Socket.C enumerates the error types.


The program DebugClient (see DebugClient.C) shows how to use the class. For simplicity, I designed this program to run from the command-line, rather than a CGI program run by the web server. I choose this approach so users could quickly run the program and see how the socket debug class works. Integrating the class into a CGI is very straight forward.

The program attempts to connect to the debug server program specified by the command-line arguments host and port (see source code). If it fails to connect, it prints a message, and the error code and exits. If it connects, it prints the test string, writes the same string over a TCP socket to debug server and reports the result of the debug server write.


The program DebugServer (see DebugServer.C) implements an example debug server [2]. This program is a simple echo server that creates a socket, binds to it and accepts connections from clients. Once it gets a connection it forks off and handles the connection. In this case it just reads a string and echoes it.


To use the client program and the debug server, cd to the directory containing the example programs and type DebugServer [port] where port is the port you want the server to listen on. For example, to run the program on port 4000, type DebugServer 4000.

In another shell cd to the directory containing the example programs and type DebugClient [host] [port] where host is the host name of the machine the server is running on (get this by typing hostname at the command prompt) and the port is the port were the server to listening (4000 for example).

You should see a text string written to the server and to the shell.


Using network sockets to write debugging and state information to a server application is a flexible and effective technique for monitoring and debugging CGI programs. Using this method, developers can quickly debug CGI's while they run within the server environment.


[1]. W. R. Steven, 1990, UNIX Network Programming. New Jersey: Prentice-Hall, Inc, pp. 88-101.
[2]. W. R. Steven, 1990, UNIX Network Programming, Network APIs: Sockets and XTI Volume 1. New Jersey: Prentice-Hall, Inc.

Code: http://groucho.eecs.umich.edu/~omalley/software/socket_debug-1.0.tar.gz

Copyright © 1998, Kevin O'Malley
Published in Issue 34 of Linux Gazette, November 1998