Como você provavelmente já sabe, o CGI, Common Gateway Interface, é um protocolo padrão para os servidores da Web executar programas, passando os dados de solicitação HTTP para o programa por meio de variáveis padrão de entrada e ambiente e retornando a saída padrão do programa como resposta HTTP. A menos que o FastCGI ou o SCGI seja usado, o programa executável é iniciado como um processo separado pelo servidor da Web para cada solicitação e destruído no final.
O GDB, o depurador da GNU, é comumente usado para depurar os programas C e C ++ e suporta anexar aos processos de execução. Como o processo CGI é de curta duração, você precisa adiar sua saída para ter tempo suficiente para anexar o depurador enquanto o processo ainda está em execução. Para depuração casual, a opção mais fácil é simplesmente usar sleep() em um loop sem fim no local do ponto de interrupção e sair do loop com o depurador, uma vez que ele for anexado ao programa. Existem outras opções mais complicadas que eu não cobro aqui.
O exemplo a seguir assume o Ubuntu Linux e o Apache.
Primeiro instale e habilite o módulo CGI:
sudo a2enmod cgi
Em seguida, configure um 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>
Observe o parâmetro TimeOut - ele se reserva 10 minutos para depuração em vez do padrão um minuto. Após o tempo limite, o Apache mata o processo CGI e retorna a resposta do tempo limite do gateway 504 .
Finalmente, reinicie o Apache:
sudo service apache2 restart
Instale ferramentas de construção:
sudo apt-get install build-essentials cmake cgdb
Clone e compilar o aplicativo:
git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git
cd debugging-cgi-applications-with-gdb
cmake .
make
Copie o aplicativo para o diretório cgi-bin :
cp cgi-debugging-example /var/www/cgi-test/cgi-bin
Abra o URL que executa o aplicativo no navegador:
http://cgi-test.example.com/cgi-bin/cgi-debugging-example
O navegador mostrará o ícone de carregamento à medida que o aplicativo entra no loop sem fim e agora pode ser anexado ao GDB.
Recomenda -se usar CGDB em vez de GDB simples. O CGDB é um front -end de maldição para o GDB que fornece a interface familiar de texto do GDB com uma tela dividida mostrando a fonte à medida que ela é executada.
Você pode encontrar o ID do processo CGI com pgrep :
pgrep -l cgi-debugging
Anexe CGDB ao processo (o processo é pausado quando o depurador anexar):
sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)
Em seguida, você precisa sair do loop Infinite e wait_for_gdb_to_attach() Função para atingir o "ponto de interrupção" em seu aplicativo. O truque aqui é sair do sleep() até chegar wait_for_gdb_to_attach() e definir o valor da variável is_waiting com o depurador para que while (is_waiting) saia:
(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
Você também pode forçar o retorno com return , mas isso pode atrapalhar o estado do aplicativo e causar falhas. Ou você pode usar next para sair das funções em vez de finish .
Depois de sair de wait_for_gdb_to_attach() , você poderá continuar depurar o programa ou deixá -lo ser executado para a conclusão:
(gdb) next
(gdb) continue
Continuing.
[Inferior 1 (process 1005) exited normally]
(gdb) quit
O navegador agora deve mostrar a saída do programa - Olá!