Comme vous le savez probablement déjà, CGI, interface de passerelle commune, est un protocole standard pour les serveurs Web pour exécuter des programmes en transmettant les données de demande HTTP dans le programme via des variables d'entrée et d'environnement standard et de renvoyer la sortie standard du programme en tant que réponse HTTP. À moins que FastCGI ou SCGI ne soient utilisés, le programme exécutable est démarré comme un processus distinct par le serveur Web pour chaque demande et démolie à la fin.
GDB, le débogueur GNU, est couramment utilisé pour déboguer les programmes C et C ++ et il prend en charge l'attachement aux processus en cours d'exécution. Comme le processus CGI est de courte durée, vous devez retarder sa sortie pour avoir suffisamment de temps pour attacher le débogueur pendant que le processus est toujours en cours d'exécution. Pour le débogage occasionnel, l'option la plus simple est simplement d'utiliser sleep() dans une boucle sans fin à l'emplacement de Breakpoint et de quitter la boucle avec le débogueur une fois qu'il est attaché au programme. Il existe d'autres options plus compliquées que je ne couvre pas ici.
L'exemple suivant suppose Ubuntu Linux et Apache.
Installez d'abord et activez le module CGI:
sudo a2enmod cgi
Configurez ensuite un hôte virtuel compatible 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>
Remarquez le paramètre TimeOut - il se réserve 10 minutes pour le débogage au lieu de la valeur par défaut d'une minute. Une fois le délai d'attente atteint, Apache tue le processus CGI et renvoie la réponse du délai d'expiration de la passerelle 504 .
Enfin, redémarrez Apache:
sudo service apache2 restart
Installer des outils de construction:
sudo apt-get install build-essentials cmake cgdb
Cloner et compiler l'application:
git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git
cd debugging-cgi-applications-with-gdb
cmake .
make
Copiez l'application dans le répertoire cgi-bin :
cp cgi-debugging-example /var/www/cgi-test/cgi-bin
Ouvrez l'URL qui exécute l'application dans le navigateur:
http://cgi-test.example.com/cgi-bin/cgi-debugging-example
Le navigateur affichera l'icône de chargement lorsque l'application entre dans la boucle sans fin et peut maintenant être jointe avec GDB.
Il est recommandé d'utiliser CGDB au lieu de GDB ordinaire. CGDB est un frontend de malédiction à GDB qui fournit l'interface de texte GDB familière avec un écran divisé affichant la source lors de son exécution.
Vous pouvez trouver l'ID de processus CGI avec pgrep :
pgrep -l cgi-debugging
Joignez CGDB au processus (le processus est interrompu lorsque le débogueur s'attache):
sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)
Ensuite, vous devez quitter la fonction Infinite Loop et wait_for_gdb_to_attach() pour atteindre le "point d'arrêt" dans votre application. L'astuce ici consiste à sortir du sleep() jusqu'à ce que vous atteigniez wait_for_gdb_to_attach() et définissez la valeur de la variable is_waiting avec le débogueur afin que while (is_waiting) sort:
(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
Vous pouvez également forcer le retour avec return , mais cela peut gâcher l'état d'application et provoquer des accidents. Ou vous pouvez utiliser next pour sortir des fonctions au lieu de finish .
Une fois que vous êtes hors de wait_for_gdb_to_attach() , vous pouvez continuer à déboguer le programme ou le laisser s'exécuter:
(gdb) next
(gdb) continue
Continuing.
[Inferior 1 (process 1005) exited normally]
(gdb) quit
Le navigateur devrait maintenant afficher la sortie du programme - Bonjour!