Como probablemente ya sepa, CGI, Common Gateway Interface, es un protocolo estándar para que los servidores web ejecuten programas al aprobar datos de solicitud HTTP al programa a través de variables estándar de entrada y entorno, y devolviendo la salida estándar del programa como respuesta HTTP. A menos que se use FastCGI o SCGI, el servidor web inicia el programa de ejecutable como un proceso separado para cada solicitud y desgarra al final.
GDB, el GNU Depugger, se usa comúnmente para depurar programas C y C ++ y admite adjuntos a los procesos de ejecución. Como el proceso CGI es de corta duración, debe retrasar su salida para tener suficiente tiempo para adjuntar el depurador mientras el proceso aún se está ejecutando. Para la depuración casual, la opción más fácil es simplemente usar sleep() en un bucle interminable en la ubicación del punto de interrupción y salir del bucle con el depurador una vez que se adjunta al programa. Hay otras opciones más complicadas que no cubro aquí.
El siguiente ejemplo asume Ubuntu Linux y Apache.
Primero instale y habilite el módulo CGI:
sudo a2enmod cgi
Luego configure un host virtual habilitado para CGI:
<VirtualHost *:80>
ServerName cgi-test.example.com
DocumentRoot /var/www/cgi-test/htdocs
CustomLog /var/log/apache2/cgi-test.access.log combined
ErrorLog /var/log/apache2/cgi-test.error.log
TimeOut 600
ScriptAlias /cgi-bin/ /var/www/cgi-test/cgi-bin/
<Directory "/var/www/cgi-test/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Tenga en cuenta el parámetro TimeOut : se reserva 10 minutos para la depuración en lugar del valor predeterminado de un minuto. Después de alcanzar el tiempo de espera, Apache mata el proceso CGI y devuelve la respuesta de tiempo de espera de la puerta de enlace 504 .
Finalmente, reinicie Apache:
sudo service apache2 restart
Instalar herramientas de compilación:
sudo apt-get install build-essentials cmake cgdb
Clon y compile la aplicación:
git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git
cd debugging-cgi-applications-with-gdb
cmake .
make
Copie la aplicación al directorio cgi-bin :
cp cgi-debugging-example /var/www/cgi-test/cgi-bin
Abra la URL que ejecuta la aplicación en el navegador:
http://cgi-test.example.com/cgi-bin/cgi-debugging-example
El navegador mostrará el icono de carga a medida que la aplicación ingresa al bucle interminable y ahora se puede conectar con GDB.
Se recomienda usar CGDB en lugar de GDB simple. CGDB es un frontend de maldiciones a GDB que proporciona la interfaz de texto GDB familiar con una pantalla dividida que muestra la fuente a medida que se ejecuta.
Puede encontrar la identificación del proceso CGI con pgrep :
pgrep -l cgi-debugging
Adjunte CGDB al proceso (el proceso se detiene cuando se adjunta el depurador):
sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)
A continuación, debe salir de la función Infinite Loop y wait_for_gdb_to_attach() para alcanzar el "punto de interrupción" en su aplicación. El truco aquí es salir del sleep() hasta que llegue a wait_for_gdb_to_attach() y establecer el valor de la variable is_waiting con el depurador para que while (is_waiting) salga:
(gdb) finish
Run till exit from 0x8a0920 __nanosleep_nocancel () at syscall-template.S:81
0x8a07d4 in __sleep (seconds=0) at sleep.c:137
(gdb) finish
Run till exit from 0x8a07d4 in __sleep (seconds=0) at sleep.c:137
wait_for_gdb_to_attach () at cgi-debugging-example.c:6
Value returned is $1 = 0
(gdb) set is_waiting = 0 # <- to exit while
(gdb) finish
Run till exit from wait_for_gdb_to_attach () cgi-debugging-example.c:6
main () at cgi-debugging-example.c:13
También puede forzar el regreso con return , pero eso puede estropear el estado de aplicación y causar bloqueos. O puede usar next para salir de las funciones en lugar de finish .
Una vez que esté fuera de wait_for_gdb_to_attach() , puede continuar depurando el programa o dejarlo ejecutarse hasta su finalización:
(gdb) next
(gdb) continue
Continuing.
[Inferior 1 (process 1005) exited normally]
(gdb) quit
El navegador ahora debería mostrar la salida del programa, ¡hola!