3

I'm developing a FastCGI application using Apache, mod_fastcgi and the fcgapp.h API. Everything works so far, but I'm failing to detect aborted connections. We need to control them, because we are sometimes doing expensive operations which have to be aborted when the user aborts the request.

I'm trying to use the SIGPIPE as indicated in the documentation, but it doesn't seem to work.

I have written a reduced test case to show my problem:

#include <iostream>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fstream>

#include "fcgio.h"

using namespace std;

void signal_handler(int signo) {
  cerr << "SIGNAL RECEIVED: " << signo << endl;
}


int main(void) {
  streambuf * cin_streambuf  = cin.rdbuf();
  streambuf * cout_streambuf = cout.rdbuf();
  streambuf * cerr_streambuf = cerr.rdbuf();

  struct sigaction sa;
  sigemptyset(&sa.sa_mask);
  sa.sa_handler = signal_handler;
  sa.sa_flags = 0;
  sigaction(SIGPIPE, &sa, NULL);
  sigaction(SIGUSR1, &sa, NULL);
  sigaction(SIGTERM, &sa, NULL);

  FCGX_Request request;

  int socketfd = FCGX_OpenSocket("/home/guillermo/fastcgi/socket", 10);
  FCGX_Init();
  FCGX_InitRequest(&request, socketfd, 0);

  while (FCGX_Accept_r(&request) == 0) {
    fcgi_streambuf cin_fcgi_streambuf(request.in);
    fcgi_streambuf cout_fcgi_streambuf(request.out);
    fcgi_streambuf cerr_fcgi_streambuf(request.err);

    cin.rdbuf(&cin_fcgi_streambuf);
    cout.rdbuf(&cout_fcgi_streambuf);
    cerr.rdbuf(&cerr_fcgi_streambuf);

    sleep(5);

    cout << "Content-type: text/html\r\n"
         << "\r\n"
         << "<html>\n"
         << "  <head>\n"
         << "    <title>Hello, World!</title>\n"
         << "  </head>\n"
         << "  <body>\n"
         << "    <h1>Hello!</h1>\n"
         << "  </body>\n"
         << "</html>\n";

    cerr << "All right" << endl;

  }
                                                                                             cin.rdbuf(cin_streambuf);
  cout.rdbuf(cout_streambuf);
  cerr.rdbuf(cerr_streambuf);

  return 0;

}

I have tried with these two different configurations for mod_fastcgi:

FastCGIExternalServer $file -socket $socket
FastCGIServer         $file -socket $socket

No matter if I abort the connection or not, I always get "All right" in the Apache error log after 5 seconds. I have tested it with curl (Ctrl-C) and from different browsers (stop button), as well as with XMLHttpRequest.abort from Javascript (which is the real-world scenario).

This is my system configuration:

  • Linux Debian 3.2.46-1 x86_64
  • Apache2 (2.2.22-13)
  • mod_fastcgi (2.4.1-SNAP-0910052249)
Guillermo
  • 81
  • 5
  • Hm, `SIGPIPE` _should_ indeed work as long as apache gets notified that the request is cancelled. Have you taken a look at the network traffic that the browser actually passes on the aborted request to the server and doesn't just set the brower up to ignore the response? – Joachim Isaksson Jun 27 '13 at 11:34
  • @JoachimIsaksson I checked with Wireshark that the client is sending a TCP RST (seq=768) to the server and initializing a new connection (SYN seq=0). The server takes the new connection (SYN, ACK) but after a few seconds, it continues with the old one as well... – Guillermo Jun 27 '13 at 12:21
  • Also tested with Lighttpd. Same program, following configuration: fastcgi.server = ( "/test" => ( "test.fastcgi.handler" => ( "socket" => "/home/guillermo/fastcgi/socket", "check-local" => "disable", "max-procs" => 0, ) ) ) Still the same... – Guillermo Jul 03 '13 at 09:17
  • Have you manually sent SIGPIPE to your process? Does it react or is the signal somehow not doing what it should? – Robert Siemer Feb 23 '15 at 16:15
  • Yes, back when I was testing this, I manually sent the signal with "kill" to check that it came through. It did work with an nginx server (instead of Apache), but we haven't upgraded to the newest Apache, so maybe it does work now. Since then, we came with a different solution, so I'm not actually following this issue anymore :/ – Guillermo Feb 25 '15 at 09:05

0 Answers0