おそらくすでにご存知のように、COMN GATEWAYインターフェイスであるCGIは、標準の入力および環境変数を介してHTTP要求データをプログラムに渡し、プログラムの標準出力をHTTP応答として返すことにより、Webサーバーの標準プロトコルです。 FastCGIまたはSCGIが使用されない限り、実行可能ファイルプログラムは、各リクエストに対してWebサーバーによって個別のプロセスとして開始され、最後に取り壊されます。
GNUデバッガーであるGDBは、一般にCおよびC ++プログラムのデバッグに使用され、実行プロセスへのアタッチをサポートします。 CGIプロセスは短命であるため、プロセスがまだ実行されている間にデバッガーを添付するのに十分な時間を確保するために、出口を遅らせる必要があります。カジュアルなデバッグの場合、最も簡単なオプションは、ブレークポイントの位置で無限のループでsleep()を使用し、プログラムに添付されたらデバッガーでループを終了することです。ここではカバーしていない他のより複雑なオプションがあります。
次の例では、Ubuntu LinuxとApacheを想定しています。
最初にインストールしてCGIモジュールを有効にします。
sudo a2enmod cgi
次に、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>
TimeOutパラメーターに注意してください - デフォルトの1分ではなく、デバッグのために10分間予約します。タイムアウトに達した後、ApacheはCGIプロセスを殺し、 504ゲートウェイタイムアウト応答を返します。
最後に、Apacheを再起動します:
sudo service apache2 restart
ビルドツールのインストール:
sudo apt-get install build-essentials cmake cgdb
アプリケーションをクローンしてコンパイルします。
git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git
cd debugging-cgi-applications-with-gdb
cmake .
make
アプリケーションをcgi-binディレクトリにコピーします。
cp cgi-debugging-example /var/www/cgi-test/cgi-bin
ブラウザでアプリケーションを実行するURLを開きます。
http://cgi-test.example.com/cgi-bin/cgi-debugging-example
ブラウザは、アプリケーションがエンドレスループに入るとロードアイコンが表示され、GDBで接続できるようになります。
プレーンGDBの代わりにCGDBを使用することをお勧めします。 CGDBは、GDBへのCurses Frontendであり、馴染みのあるGDBテキストインターフェイスを提供し、ソースが実行されるソースを表示する分割画面を提供します。
pgrepを使用してCGIプロセスIDを見つけることができます。
pgrep -l cgi-debugging
CGDBをプロセスに取り付けます(デバッガーが添付されるとプロセスが一時停止されます):
sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)
次に、アプリケーションの「ブレークポイント」に到達するには、Infinite Loopとwait_for_gdb_to_attach()関数を終了する必要があります。ここでのトリックは、 wait_for_gdb_to_attach()に到達し、デバッガーで変数is_waitingの値を設定して、 while (is_waiting)を終了するまで、 sleep()を脱出することです。
(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
また、 returnを強制することもできますが、アプリケーション状態を台無しにしてクラッシュを引き起こす可能性があります。または、 next使用して、 finishの代わりに機能から抜け出すこともできます。
wait_for_gdb_to_attach()がなくなったら、プログラムのデバッグを続けるか、完了まで実行することができます。
(gdb) next
(gdb) continue
Continuing.
[Inferior 1 (process 1005) exited normally]
(gdb) quit
ブラウザにプログラムの出力を表示する必要があります-Hello!