Bug #79991 [Com]: Connection handling mod_php and mod_fcgid

From: Date: Wed, 19 Aug 2020 10:57:19 +0000
Subject: Bug #79991 [Com]: Connection handling mod_php and mod_fcgid
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-228671@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79991&edit=1

 ID:                 79991
 Comment by:         hoover at gmx dot at
 Reported by:        hoover at gmx dot at
 Summary:            Connection handling mod_php and mod_fcgid
 Status:             Feedback
 Type:               Bug
 Package:            *General Issues
 Operating System:   Windows Server 2012
 PHP Version:        7.2.33
 Block user comment: N
 Private report:     N

 New Comment:

Thank you for your quick response.


>> A1) If we do a simple echo of the payload and a flush()
>> the client waits until 9) (until the php-script has total
>> finished). A client abort, with above functions, is never
>> detected.
> You have to send output, then check connection_aborted().

I know but that is not working as expected, considering
(with configuration as mentioned above):

1) Client requests
2) Client is disconnected (closed):

3) PHP:
header('Content-length: ' . strlen(payload));
echo {payload};
flush();
connection_aborted(); => false
connection_status(); => CONNECTION_NORMAL

I did send something to the client but the
abort is not detected by PHP, if I do:

1) Client requests
2) Client is disconnected (closed):

3) PHP:
header('Content-length: ' . strlen(payload));
echo {payload};
flush();
echo " "; <= !!!
connection_aborted(); => true
connection_status(); => !CONNECTION_NORMAL


That is weird for me.


> I'm not familiar with mod_fcgid but I suspect you're running into
> FcgidOutputBufferSize.
> https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidoutputbuffersize

Thank you for that one. I am new to work with mod_fcgid
(mod_fcgid got necessary because of an unstable
combination of Apache - SSL - mod_php). So I will test
that.


It is a pitty that connection handling is no straigth
forward work and not consistent across different
servers and mechanisms.


Regards,
AH


Previous Comments:
------------------------------------------------------------------------
[2020-08-18 15:31:51] requinix@php.net

Client aborts are essentially client-closed connections, so they aren't detected until you try
to write to that connection and TCP reports failure.
https://www.php.net/manual/en/features.connection-handling.php

> A1) If we do a simple echo of the payload and a flush()
> the client waits until 9) (until the php-script has total
> finished). A client abort, with above functions, is never
> detected.
You have to send output, then check connection_aborted().

> A2) After thousand days of trail and error we noticed that at
> least a content-length header has to be set by the php-script
> to "release the client". So 7) close connection to client
> does work. But again no chance to detect a client abort.
Correct: without a Content-Length the client has no idea how long the response is going to be. It
will hang on until the connection is closed, or
with a chunked Transfer-Encoding (IIRC what PHP does by default) until it receives a 0-length chunk
indicating the end of the response.

If you were using php-fpm (which Apache itself recommends) then you'd have access to
fastcgi_finish_request().
https://cwiki.apache.org/confluence/display/HTTPD/Php-fcgid
https://www.php.net/manual/en/function.fastcgi-finish-request.php

> A3) After thousand days of trail and error we noticed that 
> after a content-length and an echo payload and a flush()
> and at least a echo {SPACE} after the flush => detects
> a client abort.
...which satisfies the "have to send output" requirement.

> Analysed with wireshark the {SPACE} fortunately
> gets lost in TCP and not sent to the client.
PHP should not be dropping the space, so presumably your web server is.

> B1) The same thing with mod_fcgid would not work.
I'm not familiar with mod_fcgid but I suspect you're running into FcgidOutputBufferSize.
https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidoutputbuffersize

If mod_fcgid is buffering output then PHP won't know about problems until the buffer gets
flushed. Even then, I don't know how CGI/mod_fcgid handles client aborts.

------------------------------------------------------------------------
[2020-08-18 15:05:51] hoover at gmx dot at

Description:
------------
This thing is nearly version independent. The behavior can
be found with 5.4, 7.0 and 7.2.

There are many bug reports for this case but none of them has
a reproducible solution. The bug reports are starting 2005 so
this thing is long lasting.

We have a php-rest-api (no framework) that simplifies a heavy
(java) soap-api.

We have to do a lot of work after the rest/soap-processing. So,
the client of the rest-api gets a response, php should finish
the request and then php should procced with the internal work.

At the point where the client gets the response php should be
aware if client is still alive. So in short:

1) Client - requests
2) PHP - processes
3) PHP - requests soap-server
4) PHP - processes
5) PHP - repsonses to client
6) PHP - should check if client still alive
7) PHP - should close connection to client
8) PHP - processes
9) PHP finished.


So it looks like:

* ignore_user_abort = true
* No use of gzip or ...
* zlib.output_compression = 0
* output_buffering = '0'
* implicit_flush = 1;
* ob_implicit_flush(1);
* Content-Encoding: identity

Functions for connHandling:
connection_aborted()
AND
connection_status()


A) mod_php

A1) If we do a simple echo of the payload and a flush()
the client waits until 9) (until the php-script has total
finished). A client abort, with above functions, is never
detected.

A2) After thousand days of trail and error we noticed that at
least a content-length header has to be set by the php-script
to "release the client". So 7) close connection to client
does work. But again no chance to detect a client abort.

A3) After thousand days of trail and error we noticed that 
after a content-length and an echo payload and a flush()
and at least a echo {SPACE} after the flush => detects
a client abort. Analysed with wireshark the {SPACE} fortunately
gets lost in TCP and not sent to the client.

Perfect!

BUT,

B) mod_fcgid

B1) The same thing with mod_fcgid would not work.



It was really hard to find out how connection handling has actually to
be done in this scenario. The php docs are not very helpful here.
Other bug reports are also not very helpful.


So my bug report is at least a question to the php developers:

What is the right and reliable way for connection handling (in
this scenario) wiht mod_php and mod_fcgid?


Regards,
AH



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=79991&edit=1


Thread (4 messages)

« previous php.bugs (#228671) next »