Can I detect when a client has disconnected from a CGI?

Solution 1:

Usually, you can't detect broken connection until you start writing back to user. Otherwise, your process will continue doing its work without noticing connection abort from user side. This post is related even if it talks about PHP. The concept should be the same.

There are possible things you can try:

  1. Do the time-consuming work in background. When a user requests the CGI, don't execute the task as a normal blocking call. Just return anything to the user to tell that request is under processing. Of course, you need to find some way to update the view or provide another page to check for job status using some request ID or IP.
  2. Send data back to client as soon as possible and exit if failed to send (indication of broken connection). You can for example send progress of job every few seconds or minutes.

If you save the currently running jobs in a database, you can save request ID and/or client IP address. So, you can detect and ignore duplicate requests to same resource telling the user "you request is under processing".

Solution 2:

Warning: this information may be obsolete. See last paragraph.

I remember having had the same problem, and solving it with a nph (no parse header) CGI script.

Normally, apache collects all the headers from your script, and when finished reading headers, amends them with some standard headers you didn't provide. Which also means, as long as you don't finish the headers, apache sends nothing to the client at all.

With an nph script, you'll have to provide all the headers, but apache will send them to the client immediately, and send your CGI script a SIGPIPE once the client disconnects. So you can send some X-Slowly-Counting-Part-nnn: yes header every few seconds, to prevent timeouts on the client, and you'll get notified if the clients breaks the connection.

This still leaves the problem you'll have to send the HTTP Status first, but if you send a 'Content-Length: 0', or maybe a 'Content-Length: 1' and close the connection without sending any content, your file downloader should assume a network error and act accordingly.

You will probably have to pipe the output of the other program through your process, but this shouldn't be a major performance hit at least if you're on linux and use the sendfile(2) system call.

The problem with all of this is i used it at least 10 years ago, probably on Apache 1.3, and googling for apache cgi nph didn't yield anything useful. So maybe the nph feature was taken out in the meanwhile - but then, maybe not, i admit i didn't look very hard.

Solution 3:

Old question, but i had the same problem and solve checking if connection is stablished:

In my case, i'm running one bash scripting on server.. the env variables are exported by mod_cgi I believe this solution will works for any program/script running on CGI

ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
     # Client closed browser/connection
fi