Dear mod_perl list,

please consider my gratefulness for any hints/insight :)

I'm trying to achieve the following: when there is an incoming request, I want to set a time limit in which an answer should be delivered to the client, no matter what.

However, since the work triggered by the initial request (there is another request to other site involved) might take much longer than that time limit, I want that work to properly finish, despite the fact that the initial request was 'served' already.

I first thought that using alarm and closing the connection would just work, so my initial code was somewhat like


---

#!/usr/bin/perl

use strict;
use warnings;

use Apache2::RequestUtil;
use Apache2::Connection;
use Apache2::Const -compile => qw(:common :http );

local our $r = shift;

local our $t_start = time();
local $SIG{ALRM} = sub { _force_early_response( $t_start ) };

local our $it_took_too_long = 0;

our $alarm_time = 5; # seconds we allow to process an response

alarm $alarm_time;

# start working for the request
#
# work done

alarm 0
return Apache2::Const::OK;


sub _force_early_response {
    my ($t1) = @_;

    $it_took_too_long = 1;

    my $t2 = time();

    $r->assbackwards(1);
    my $response_text = _sorry_but_that_will_be_ready_only_later();

    $r->print( "HTTP/1.1 200 OK\n"
              ."Date: Wed, 20 Apr 2016 10:55:08 GMT\n"
              ."Server: Apache/2.2.31 (Amazon)\n"
              ."Content-Type: text/plain; charset=UTF-8\n");

    $r->print( "\n$response_text" );

    my $c = $r->connection();
    my $socket = $c->client_socket;

    $socket->close();
    return;
}
---

That didn't work - the connection just was not closed.

A second attempt succeeded, where I changed the alarm trap to be

---
sub _force_early_response {
    my ($t1) = @_;

    $it_took_too_long = 1;

    my $t2 = time();

    $r->assbackwards(1);

    my $response_text = _sorry_but_that_will_be_ready_only_later();
    my $content_length = length( $response_text );

    $r->print( "HTTP/1.1 200 OK\n"
              ."Date: Wed, 20 Apr 2016 10:55:08 GMT\n"
              ."Server: Apache/2.2.31 (Amazon)\n"
              ."Connection: close\n"
              ."Content-Type: text/plain; charset=UTF-8\n"
              ."Content-Length: $content_length\n" );

    $r->print( "\n$response_text" );
    return;
}
---

So while I have now something that seems to work OK and does exactly what I wanted, I'm a bit unhappy with the code.

I did look around, but I wasn't able to find any mod_perl/library function that would make the 'close connection and go on' code easier.

Especially for setting the status line, what I now do by

   $r->print( "HTTP/1.1 200 OK\n" )

I thought that there would be some ready-made tools available.

I actually hoped to get away without having to explicitely write out 'hand-crafted' headers, but so far I wasn't able to find anything for that.

Maybe I just didn't look into the right places?

I'm running this on an updated Amazon Linux machine, vanilla httpd and mod_perl,

$ rpm -qi httpd
Name        : httpd
Version     : 2.2.31
Release     : 1.7.amzn1

$ rpm -qi mod_perl
Name        : mod_perl
Version     : 2.0.7
Release     : 7.27.amzn1

Many thanks in advance for any ideas, hints, comments.

Iosif Fettich

Reply via email to