Mailing List Archive

[mod_backhand-users] Back again
Hi Theo, hi list,

it's definitley a long time since my last post... but i promised you to send
you the perl script which i used to fool a backhand moderator to proxy
requests to a NT server... and here it is (someone asked for it a few weeks
ago)

---cut here---
#!/usr/bin/perl
use Socket;
use Sys::Hostname;

$iaddr = gethostbyname('0.0.0.0');
$proto = getprotobyname('udp');
$paddr = sockaddr_in(4445, $iaddr);

socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!";

$hisiaddr = inet_aton('192.168.0.1') || die "unknown host";
$hispaddr = sockaddr_in(4445, $hisiaddr);

while(1) {
$buf = pack("a40N*", 'my.server.de', 0, 80, 3232235522, 0, 0,
414309, 0, 0, 80, 2097152000, 1000, 1, 131002368, 101639360,

0, 0);
defined(send(SOCKET, $buf, 0, $hispaddr)) || warn "send $host:
$!";
sleep 1;
}
---cut here---

Most of it is ripped from the perlipc manpage and the for pack() are those
i've recorded before for a mod_backhand broadcast. If you like to try this
script... simply adjust the ip address in line 11 to the adress you want to
send to (the mod_backhand amchine) and replace 3232235522 with the ip of the
machine you are simulating the broadcasts for... (3232235522 is 192.168.0.2:
192*256*256*256 + 168*256*256 + 0*256 + 2 = 3232235522)

Yes, i agree, this is very very ugly... but it's done it's job pretty good
for a long time and since it's pretty short I used as sort of introduction
example before i present to you the real mad script:

---cut here---
use Win32::PerfLib;
use Socket;
use Sys::Hostname;

my $server = "";
my $system_obj = 2;
my $cpu_id = 240;

## if the defaults defined above do not work you may uncomment the
## following lines to rederterminate the correct ids
#Win32::PerfLib::GetCounterNames($server, \%counter);
## reverse hash
#%r_counter = map { $counter{$_} => $_ } keys %counter;
## retrieve the id for process object
#$system_obj = $r_counter{'System'};
## retrieve the id for the process ID counter
#$cpu_id = $r_counter{'% Total Processor Time'};

# create udp socket
$iaddr = gethostbyname(hostname());
$proto = getprotobyname('udp');
$paddr = sockaddr_in(0, $iaddr);
socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!";

# our moderator we are broadcasting to
$hisiaddr = inet_aton('192.168.0.1') || die "unknown host";
$hispaddr = sockaddr_in(4445, $hisiaddr);

# create connection to $server
$perflib = new Win32::PerfLib($server);

$proc_ref = {};
$proc_ref2 = {};
# get the performance data for the system object
$perflib->GetObjectList($system_obj, $proc_ref);
while(1) {
sleep 3;
$perflib->GetObjectList($system_obj, $proc_ref2);
$perflib->Close();

$counter_ref=$proc_ref->{Objects}->{$system_obj}->{Counters};
$counter_ref2=$proc_ref2->{Objects}->{$system_obj}->{Counters};
foreach $i (keys %{$counter_ref}) {
if ($counter_ref->{$i}->{CounterNameTitleIndex} == $cpu_id)
{
$Numerator0 = $counter_ref->{$i}->{Counter};
$Denominator0 = $proc_ref->{PerfTime100nSec};
$Numerator1 = $counter_ref2->{$i}->{Counter};
$Denominator1 = $proc_ref2->{PerfTime100nSec};
$idle = ((($Numerator1 - $Numerator0) /
($Denominator1 - $Denominator0 ))) * 1000;
}
}
$buf = pack("a40N*", hostname(), 0, 80, unpack('N', $iaddr),
0, 0, 414309, 0, 0, 80, 2097152000, $idle,
1, 131002368, 101639360, 0, 0);
defined(send(SOCKET, $buf, 0, $hispaddr)) || warn "send $host: $!";
$proc_ref = $proc_ref2;
$proc_ref2 = {};
$perflib->GetObjectList($system_obj, $proc_ref2);
}
---cut here---

As the "use Win32" staement suggests... yes, this script is intended to run
under windows... it queries the performance counters to get the current cpu
load (System/Total Processor Time) and sends the information to the
moderator. Pretty easy, huh? Works with ActivePerl and WinNT; Haven't tested
with Win2000 or other perl ports so far. Of course it would be a much better
deal to do this in C and I'm looking forward to see the implemention someone
has announced because this perl variant is inaccurate and consumes too much
resources on the web server.

Back to mod_backhand itself... i've now been running (and I still am) the
following combination "Apache/1.3.19 (Unix) mod_gzip/1.3.19.1a
balanced_by_mod_backhand/1.1.1pre4" for some months. The Linux server
accepts the requests from the internet proxies them to an nt server using
mod_backhand and compresses the results with mod_gzip. Now I am installing a
second nt server and a second moderator because the two old servers are no
longer able to handle the load. Having played around with the
mod_gzip/mod_backhand combination for serveral days now, i've got the
following questions:

1) bySession
Quoted from builtins.c:
/* Note: this won't work if the client sends more than one cookie.
* I've tested mozilla M18, sends one cookie header containing all
* variables that have been set via cookies. Hope this is standard
* and all the other clients act the same way.
*/
This is a bit confusing to me... when I read this comment I understand the
following "if more than one cookie is set bySession will not work." But when
I read the code it tells me "It will work aslong as the browser returns all
cookies in one single line" (which I can confirm for MSIE and Opera, too).
So, what is the rigth interpretation?

2) HTTP Status Code 100 - continue
For some very strange reasons the IIS likes "100 - continue" responses.
According to the rfc the client has to ignore this response and must wait
for another http header. However this seems to be causing problems with
mod_backhand since mod_backhand sends the 100-continue response to the
client and closes the connection immediately. The user agent which expected
another header after the 100-continue is "very surprised" about this and
displays an error message. I patched my 1.1.1pre4 to simply read another
header when it recieves an 100-continue from the server it proxies to. The
way it is implemented is not very nice and it has most probably a memory
leak, however it works, it even works with mod_backhand1.2.0:

(patch against mod_backhand1.2.0)
---cut here---
@@ -710,6 +710,9 @@
ap_clear_table(r->headers_out);
rv = b_get_mime_headers_out(myconn, r,
&myconn_headers_rcvd, &cookies_rcvd);
+ if(r->status == 100) //reread if 100;
+ rv = b_get_mime_headers_out(myconn, r,
+ &myconn_headers_rcvd, &cookies_rcvd);
ap_overlap_tables(r->headers_out, myconn_headers_rcvd,
AP_OVERLAP_TABLES_SET);
if(!ap_is_empty_table(cookies_rcvd)) {
---cut here---

In the changelog for 1.2.0 there is the following entry: "Fixed RFC
compliance issue with HTTP response codes that are 304, 204, and less that
200. They are explicitly defined to have no content length". Does this the
same problem the three lines above do? A quick grep of the source code told
me there are not other handlers for http 100 status codes but i may be
wrong... Any comments on that?

3) ap_is_initial_req()

Again this is a patch i first used against mod_backhand_1.1.1pre4 and again
it is neccessary to make mod_backhand1.2.0 work as expected. As I've
explained before I use mod_gzip to compress the content before sending it
back to the user. having mod_gzip in the modules chain before mod_backhand
ap_is_inital_req(r) is no longer true for any request mod_backhand gets...
so I had to comment out the if block as shown in the patch below. Again this
most probaly is very bad style because I'm sure you had your reasons to but
it in... Is there a clean solution for that problem?

---cut here---
@@ -1247,7 +1250,7 @@
}
}
} else {
- if(ap_is_initial_req(r)) {
+// if(ap_is_initial_req(r)) {
request_rec *subr;
mbcfg *tmpcfg;
ap_table_setn(r->notes, "BackhandProxyRequest", "YES");
@@ -1270,10 +1273,10 @@
}
ap_destroy_sub_req(subr);
return OK;
- } else {
+/* } else {
ap_table_setn(r->notes, "BackhandProxyRequest", "NO");
ap_destroy_sub_req(subr);
- }
+ }*/
}
}
if(loglevel & MBLL_DCSN1) {
---cut here---

4) Graceful restart causes problems
I think the answer to this question is hidden somewhere in my patches i
presented above... when ia ask apache to do a graceful restart some childs
(about 1-3 of 200) refuse to kill themselves but start consuming very high
amounts of memory and cpu. Do you see any reasons why I am experiencing this
strange behaviour?


Thank you in advance

Stefan


This is the complete patch:
--- mod_backhand-1.2.0/mod_backhand.c Wed May 30 23:05:17 2001
+++ mod_backhand-1.2.0.patched/mod_backhand.c Tue Sep 18 19:03:29 2001
@@ -710,6 +710,9 @@
ap_clear_table(r->headers_out);
rv = b_get_mime_headers_out(myconn, r,
&myconn_headers_rcvd, &cookies_rcvd);
+ if(r->status == 100) //reread if 100;
+ rv = b_get_mime_headers_out(myconn, r,
+ &myconn_headers_rcvd, &cookies_rcvd);
ap_overlap_tables(r->headers_out, myconn_headers_rcvd,
AP_OVERLAP_TABLES_SET);
if(!ap_is_empty_table(cookies_rcvd)) {
@@ -1247,7 +1250,7 @@
}
}
} else {
- if(ap_is_initial_req(r)) {
+// if(ap_is_initial_req(r)) {
request_rec *subr;
mbcfg *tmpcfg;
ap_table_setn(r->notes, "BackhandProxyRequest", "YES");
@@ -1270,10 +1273,10 @@
}
ap_destroy_sub_req(subr);
return OK;
- } else {
+/* } else {
ap_table_setn(r->notes, "BackhandProxyRequest", "NO");
ap_destroy_sub_req(subr);
- }
+ }*/
}
}
if(loglevel & MBLL_DCSN1) {
[mod_backhand-users] Back again [ In reply to ]
On Thursday, September 20, 2001, at 04:46 PM, Seufert, Stefan wrote:
> 1) bySession
> Quoted from builtins.c:
> /* Note: this won't work if the client sends more than one cookie.
> * I've tested mozilla M18, sends one cookie header containing all
> * variables that have been set via cookies. Hope this is standard
> * and all the other clients act the same way.
> */
> This is a bit confusing to me... when I read this comment I understand
> the
> following "if more than one cookie is set bySession will not work." But
> when
> I read the code it tells me "It will work aslong as the browser returns
> all
> cookies in one single line" (which I can confirm for MSIE and Opera,
> too).
> So, what is the rigth interpretation?

If their are multiple Cookie headers in the inbound request then the
bySession function will not necessarily find the cookie that you are
looking for.

> 2) HTTP Status Code 100 - continue
> For some very strange reasons the IIS likes "100 - continue" responses.
> According to the rfc the client has to ignore this response and must
> wait
> for another http header. However this seems to be causing problems with
> mod_backhand since mod_backhand sends the 100-continue response to the
> client and closes the connection immediately. The user agent which
> expected
> another header after the 100-continue is "very surprised" about this and
> displays an error message. I patched my 1.1.1pre4 to simply read another
> header when it recieves an 100-continue from the server it proxies to.
> The
> way it is implemented is not very nice and it has most probably a memory
> leak, however it works, it even works with mod_backhand1.2.0:
>
> (patch against mod_backhand1.2.0)
> ---cut here---
> @@ -710,6 +710,9 @@
> ap_clear_table(r->headers_out);
> rv = b_get_mime_headers_out(myconn, r,
> &myconn_headers_rcvd, &cookies_rcvd);
> + if(r->status == 100) //reread if 100;
> + rv = b_get_mime_headers_out(myconn, r,
> + &myconn_headers_rcvd, &cookies_rcvd);
> ap_overlap_tables(r->headers_out, myconn_headers_rcvd,
> AP_OVERLAP_TABLES_SET);
> if(!ap_is_empty_table(cookies_rcvd)) {
> ---cut here---
>
> In the changelog for 1.2.0 there is the following entry: "Fixed RFC
> compliance issue with HTTP response codes that are 304, 204, and less
> that
> 200. They are explicitly defined to have no content length". Does this
> the
> same problem the three lines above do? A quick grep of the source code
> told
> me there are not other handlers for http 100 status codes but i may be
> wrong... Any comments on that?

Nope.. there was a <200 if that forced the content length to 0... the
use of 100's is just disgusting.

I've commit your fix for it to CVS.

> 3) ap_is_initial_req()
>
> Again this is a patch i first used against mod_backhand_1.1.1pre4 and
> again
> it is neccessary to make mod_backhand1.2.0 work as expected. As I've
> explained before I use mod_gzip to compress the content before sending
> it
> back to the user. having mod_gzip in the modules chain before
> mod_backhand
> ap_is_inital_req(r) is no longer true for any request mod_backhand
> gets...
> so I had to comment out the if block as shown in the patch below. Again
> this
> most probaly is very bad style because I'm sure you had your reasons to
> but
> it in... Is there a clean solution for that problem?

I couldn't get it to work at all without that. Very very strange
indeed. I am hesitant to commit your change until I try it out in some
various ways.

I would be really helpful if other people could patch their version and
see if it works for them. Anyone??? (patch at bottom)

> 4) Graceful restart causes problems
> I think the answer to this question is hidden somewhere in my patches i
> presented above... when ia ask apache to do a graceful restart some
> childs
> (about 1-3 of 200) refuse to kill themselves but start consuming very
> high
> amounts of memory and cpu. Do you see any reasons why I am experiencing
> this
> strange behaviour?

Very strange. If they are spinning over system calls, it will be easier
to track down the problem. Can you strace one of the rogue processes?
What is it doing? If it is just spinning on CPU, then you will need to
be clever with gdb to track it down.

--- mod_backhand-1.2.0/mod_backhand.c Wed May 30 23:05:17 2001
+++ mod_backhand-1.2.0.patched/mod_backhand.c Tue Sep 18 19:03:29 2001
@@ -1247,7 +1250,7 @@
}
}
} else {
- if(ap_is_initial_req(r)) {
+// if(ap_is_initial_req(r)) {
request_rec *subr;
mbcfg *tmpcfg;
ap_table_setn(r->notes, "BackhandProxyRequest", "YES");
@@ -1270,10 +1273,10 @@
}
ap_destroy_sub_req(subr);
return OK;
- } else {
+/* } else {
ap_table_setn(r->notes, "BackhandProxyRequest", "NO");
ap_destroy_sub_req(subr);
- }
+ }*/
}
}
if(loglevel & MBLL_DCSN1) {


--
Theo Schlossnagle
1024D/82844984/95FD 30F1 489E 4613 F22E 491A 7E88 364C 8284 4984
2047R/33131B65/71 F7 95 64 49 76 5D BA 3D 90 B9 9F BE 27 24 E7
[mod_backhand-users] Back again [ In reply to ]
Hi,

> If their are multiple Cookie headers in the inbound request then the
> bySession function will not necessarily find the cookie that you are
> looking for.

... but if multiple Cookies are sent back in one single header ("line") then
it does work, right? As far as I can tell all (important) browsers are doing
so.

> > 2) HTTP Status Code 100 - continue
> > [...]
> > (patch against mod_backhand1.2.0)
> > ---cut here---
> > @@ -710,6 +710,9 @@
> > ap_clear_table(r->headers_out);
> > rv = b_get_mime_headers_out(myconn, r,
> > &myconn_headers_rcvd, &cookies_rcvd);
> > + if(r->status == 100) //reread if 100;
> > + rv = b_get_mime_headers_out(myconn, r,
> > + &myconn_headers_rcvd, &cookies_rcvd);
> > ap_overlap_tables(r->headers_out, myconn_headers_rcvd,
> > AP_OVERLAP_TABLES_SET);
> > if(!ap_is_empty_table(cookies_rcvd)) {
> > ---cut here---
>
> I've commit your fix for it to CVS.

Isn't there some sort of memory leak because of not destroying the first
myconn_hraders_rcvd and cookies_rcvd tables? I do not know the apche table
functions at all, so I am wondering if there shouldn't be a call to some
sort of destory or free function...

> > 3) ap_is_initial_req()
>
> I couldn't get it to work at all without that. Very very strange
> indeed. I am hesitant to commit your change until I try it
> out in some
> various ways.
>
> I would be really helpful if other people could patch their
> version and see if it works for them. Anyone???

I'll try it without mod_gzip and report what happend tomorrow.

> > 4) Graceful restart causes problems

> Very strange. If they are spinning over system calls, it
> will be easier to track down the problem. Can you strace
> one of the rogue processes? What is it doing? If it is
> just spinning on CPU, then you will need to
> be clever with gdb to track it down.

I told the sysadmins to do so if they get tehier hands on one of those
processes. Let's see what we get.

Again, thank you for your help,

Stefan
[mod_backhand-users] Back again [ In reply to ]
Seufert, Stefan wrote:
>>If their are multiple Cookie headers in the inbound request then the
>>bySession function will not necessarily find the cookie that you are
>>looking for.
>>
>
> ... but if multiple Cookies are sent back in one single header ("line") then
> it does work, right? As far as I can tell all (important) browsers are doing
> so.

Yup.


>>> rv = b_get_mime_headers_out(myconn, r,
>>> &myconn_headers_rcvd, &cookies_rcvd);
>>>+ if(r->status == 100) //reread if 100;
>>>+ rv = b_get_mime_headers_out(myconn, r,
>>>+ &myconn_headers_rcvd, &cookies_rcvd);
>
> Isn't there some sort of memory leak because of not destroying the first
> myconn_hraders_rcvd and cookies_rcvd tables? I do not know the apche table
> functions at all, so I am wondering if there shouldn't be a call to some
> sort of destory or free function...

There shouldn't be. The allocations should be done in the memory pool
associated with "r" (the request). When the request terminates, it will be
freed (all of it).

--
Theo Schlossnagle
1024D/82844984/95FD 30F1 489E 4613 F22E 491A 7E88 364C 8284 4984
2047R/33131B65/71 F7 95 64 49 76 5D BA 3D 90 B9 9F BE 27 24 E7
[mod_backhand-users] Back again [ In reply to ]
Hi,

> > 3) ap_is_initial_req()
> >
> > Again this is a patch i first used against
> > [...]
> > it in... Is there a clean solution for that problem?
>
> I couldn't get it to work at all without that. Very very strange
> indeed. I am hesitant to commit your change until I try it
> out in some various ways.
>
> I would be really helpful if other people could patch their
> version and see if it works for them. Anyone??? (patch at bottom)

Since the major difference between most setups out there and my setup seems
to be the use of mod_gzip I left mod_gzip out and played around with the
patched version. Everything still works fine, no problems.

- Apache/1.3.19 (Unix) (SuSE/Linux) mod_layout/1.0
mod_throttle/3.0 mod_fastcgi/2.2.2 mod_ssl/2.8.3
OpenSSL/0.9.6a mod_perl/1.25 mod_gzip/1.3.19.1a
mod_dtcl balanced_by_mod_backhand/1.2.0

- Linux version 2.4.9 (root@rz-gz1) (gcc version 2.95.3
20010315 (SuSE)) #2 SMP Thu Sep 6 14:58:17 CEST 2001

Maybe this helps...

Stefan
[mod_backhand-users] Back again [ In reply to ]
On Sunday, September 23, 2001, at 01:31 PM, Seufert, Stefan wrote:
>> I would be really helpful if other people could patch their
>> version and see if it works for them. Anyone??? (patch at bottom)
>
> Since the major difference between most setups out there and my setup
> seems
> to be the use of mod_gzip I left mod_gzip out and played around with the
> patched version. Everything still works fine, no problems.
>
> - Apache/1.3.19 (Unix) (SuSE/Linux) mod_layout/1.0
> mod_throttle/3.0 mod_fastcgi/2.2.2 mod_ssl/2.8.3
> OpenSSL/0.9.6a mod_perl/1.25 mod_gzip/1.3.19.1a
> mod_dtcl balanced_by_mod_backhand/1.2.0
>
> - Linux version 2.4.9 (root@rz-gz1) (gcc version 2.95.3
> 20010315 (SuSE)) #2 SMP Thu Sep 6 14:58:17 CEST 2001
>
> Maybe this helps...

This is enough evidence for me ;-)= .. It is now in CVS. Thanks!

--
Theo Schlossnagle
1024D/82844984/95FD 30F1 489E 4613 F22E 491A 7E88 364C 8284 4984
2047R/33131B65/71 F7 95 64 49 76 5D BA 3D 90 B9 9F BE 27 24 E7