{"id":21984679,"url":"https://github.com/mrts/debugging-cgi-applications-with-gdb","last_synced_at":"2026-05-03T13:36:37.364Z","repository":{"id":66661236,"uuid":"91616344","full_name":"mrts/debugging-cgi-applications-with-gdb","owner":"mrts","description":"How to debug CGI applications with GDB","archived":false,"fork":false,"pushed_at":"2018-02-08T19:07:08.000Z","size":10,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-28T05:14:25.129Z","etag":null,"topics":["c","cgi","gdb"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mrts.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-17T20:16:01.000Z","updated_at":"2023-02-12T16:35:12.000Z","dependencies_parsed_at":"2023-05-02T04:02:31.846Z","dependency_job_id":null,"html_url":"https://github.com/mrts/debugging-cgi-applications-with-gdb","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrts%2Fdebugging-cgi-applications-with-gdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrts%2Fdebugging-cgi-applications-with-gdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrts%2Fdebugging-cgi-applications-with-gdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrts%2Fdebugging-cgi-applications-with-gdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrts","download_url":"https://codeload.github.com/mrts/debugging-cgi-applications-with-gdb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245044493,"owners_count":20551898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cgi","gdb"],"created_at":"2024-11-29T18:10:44.282Z","updated_at":"2026-05-03T13:36:32.321Z","avatar_url":"https://github.com/mrts.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to debug CGI applications written in C/C++ with GDB\n\nAs you probably already know, CGI, Common Gateway Interface, is a standard\nprotocol for web servers to execute programs by passing HTTP request data into\nthe program via standard input and environment variables, and returning the\nprogram's standard output as the HTTP response. Unless FastCGI or SCGI is used,\nthe executable program is started as a separate process by the web server\nfor each request and torn down at the end.\n\nGDB, the GNU Debugger, is commonly used to debug C and C++ programs and it\nsupports attaching to running processes. As the CGI process is short-lived, you\nneed to delay its exit to have enough time to attach the debugger while the\nprocess is still running. For casual debugging the easiest option is to simply\nuse `sleep()` in an endless loop at the breakpoint location and exit the loop\nwith the debugger once it is attached to the program. There are other, more\ncomplicated options that I don't cover here.\n\nThe following example assumes Ubuntu Linux and Apache.\n\n## Setting up CGI support in Apache\n\nFirst install and enable the CGI module:\n\n    sudo a2enmod cgi\n\nThen configure a CGI-enabled virtual host:\n\n    \u003cVirtualHost *:80\u003e\n        ServerName      cgi-test.example.com\n        DocumentRoot    /var/www/cgi-test/htdocs\n        CustomLog       /var/log/apache2/cgi-test.access.log combined\n        ErrorLog        /var/log/apache2/cgi-test.error.log\n\n        TimeOut         600\n\n        ScriptAlias /cgi-bin/ /var/www/cgi-test/cgi-bin/\n\n        \u003cDirectory \"/var/www/cgi-test/cgi-bin\"\u003e\n            AllowOverride None\n            Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch\n            Order allow,deny\n            Allow from all\n        \u003c/Directory\u003e\n    \u003c/VirtualHost\u003e\n\nNote the `TimeOut` parameter - it reserves 10 minutes for debugging instead of\nthe default one minute. After timeout is reached, Apache kills the CGI process\nand returns the *504 Gateway timeout* response.\n\nFinally, restart Apache:\n\n    sudo service apache2 restart\n\n## Compiling and running the example CGI application\n\nInstall build tools:\n\n    sudo apt-get install build-essentials cmake cgdb\n\nClone and compile the application:\n\n    git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git\n    cd debugging-cgi-applications-with-gdb\n    cmake .\n    make\n\nCopy the application to `cgi-bin` directory:\n\n    cp cgi-debugging-example /var/www/cgi-test/cgi-bin\n\nOpen the URL that runs the application in browser:\n\n\u003chttp://cgi-test.example.com/cgi-bin/cgi-debugging-example\u003e\n\nThe browser will show the loading icon as the application enters the endless\nloop and can now be attached to with GDB.\n\n## Attaching the debugger and debugging\n\nIt is recommended to use CGDB instead of plain GDB. CGDB is a curses frontend\nto GDB that provides the familiar GDB text interface with a split screen\nshowing the source as it executes.\n\nYou can find the CGI process ID with `pgrep`:\n\n    pgrep -l cgi-debugging\n\nAttach CGDB to the process (the process is paused when debugger attaches):\n\n    sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)\n\nNext you need to exit the infinite loop and `wait_for_gdb_to_attach()` function\nto reach the \"breakpoint\" in your application. The trick here is to step out of\n`sleep()` until you reach `wait_for_gdb_to_attach()` and set the value of the\nvariable `is_waiting` with the debugger so that `while (is_waiting)` exits:\n\n    (gdb) finish\n    Run till exit from 0x8a0920 __nanosleep_nocancel () at syscall-template.S:81\n    0x8a07d4 in __sleep (seconds=0) at sleep.c:137\n    (gdb) finish\n    Run till exit from 0x8a07d4 in __sleep (seconds=0) at sleep.c:137\n    wait_for_gdb_to_attach () at cgi-debugging-example.c:6\n    Value returned is $1 = 0\n    (gdb) set is_waiting = 0 # \u003c- to exit while\n    (gdb) finish\n    Run till exit from wait_for_gdb_to_attach () cgi-debugging-example.c:6\n    main () at cgi-debugging-example.c:13\n\nYou could also force return with `return`, but that may mess up application\nstate and cause crashes. Or you could use `next` to step out of functions\ninstead of `finish`.\n\nOnce you are out of `wait_for_gdb_to_attach()`, you can continue debugging the\nprogram or let it run to completion:\n\n    (gdb) next\n    (gdb) continue\n    Continuing.\n    [Inferior 1 (process 1005) exited normally]\n    (gdb) quit\n\nThe browser should now show the program output - *Hello!*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrts%2Fdebugging-cgi-applications-with-gdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrts%2Fdebugging-cgi-applications-with-gdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrts%2Fdebugging-cgi-applications-with-gdb/lists"}