Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

connection_status and connection_aborted does not work #10106

Open
seltix5 opened this issue Oct 23, 2022 · 29 comments
Open

connection_status and connection_aborted does not work #10106

seltix5 opened this issue Oct 23, 2022 · 29 comments

Comments

@seltix5
Copy link

seltix5 commented Oct 23, 2022

From manual page: https://php.net/function.connection-status

Hi,
I tested this using PHP 7.4 but it does not detect disconnect, I try to stop and close the browser.

<?php
ignore_user_abort(true);
set_time_limit(0);

while(1)
{
    echo "\n";
    ob_flush();
    flush();

    // Did the connection fail?
    if(connection_status() != CONNECTION_NORMAL)
    {
        break;
    }

    sleep(1);
}

@cmb69
Copy link
Contributor

cmb69 commented Nov 2, 2022

Did you mean to report this as actual bug, or as documentation issue?

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

hi,
I supose if the code is as it should and there is no documented reasons for this to not work, it is a bug

( sorry for delay, did not get the a notification =s )

@stramunin
Copy link

@seltix5
What should not work?

ignore_user_abort(true);
set_time_limit(0);
error_log('start');
while(1)
{
    echo "\n";
    ob_flush();
    flush();

    // Did the connection fail?
    if(connection_status() != CONNECTION_NORMAL)
    {
        break;
    }

    sleep(1);
}
error_log('stop');

Built-in web-server.
I open the browser and close after a few seconds.

[Thu Dec 15 14:36:42 2022] 127.0.0.1:52133 Accepted
[Thu Dec 15 14:36:42 2022] start
[Thu Dec 15 14:36:48 2022] stop
[Thu Dec 15 14:36:48 2022] 127.0.0.1:52133 [200]: GET /
[Thu Dec 15 14:36:48 2022] 127.0.0.1:52133 Closing

@cmb69
Copy link
Contributor

cmb69 commented Dec 15, 2022

Indeed, this works as expected with the built-in Webserver.

Which SAPI do you use, @seltix5? Also note that PHP 7.4 is no longer supported, so please check with any of the actively supported PHP versions.

@stramunin
Copy link

Checked with php-fpm, also works.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

hello,
I just tested with PHP Version 8.1.13 and it does not work for me either, I never get the 'stop' output after stoping the request.
I tested this with chrome.

Server API : LiteSpeed V8.1 Cloudlinux 1.3
(btw, my host is on a shared server in case that matters)

@cmb69
Copy link
Contributor

cmb69 commented Dec 15, 2022

I never get the 'stop' output after stoping the request.

Well, no output is supposed to be shown in the browser after you've closed the tab.

Anyhow, there might be an issue with the lsapi.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

lol, output in the log file after the 'start' line. I got the 'start' line but never got the 'stop' after stoping the request.

image

what should I do then? report to LiteSpeed devs? ( https://www.litespeedtech.com/support/forum/forums/bug-reports.9/ )

@stramunin
Copy link

@seltix5
First, try a different webserver if possible and post what happens.

@KapitanOczywisty
Copy link

I've tested that on LiteSpeed V8.0.1 (Cloudlinux 1.3) and seems like php process is just killed.

2022-12-15 15:04:00.397122 [NOTICE] [145821] [T0] [xxxx:xxxx#APVH_www.xxxx] [STDERR] start
2022-12-15 15:04:04.441395 [INFO] [145821] [T0] [xxxx:xxxx#APVH_www.xxxx] Abort request processing by PID:180596, kill: 1, begin time: 4, sent time: 4, req processed: 0

@seltix5 can you run following code?

<?php
error_reporting(-1);
ini_set('display_errors', '1');
ignore_user_abort(true);
set_time_limit(30);

register_shutdown_function(function() {error_log('shutdown');});

error_log('start');
for($i = 0; $i < 20; ++$i)
{
    echo "\n";
    ob_flush();
    flush();

    // Did the connection fail?
    if(connection_status() != CONNECTION_NORMAL)
    {
error_log('abort');
        break;
    }

    sleep(1);
}
error_log('loop end');

@stramunin
Copy link

@KapitanOczywisty
I think by setting set_time_limit the sleep duration will be ignored. There must be another reason why the script is aborted.

@KapitanOczywisty
Copy link

I think by setting set_time_limit the sleep duration will be ignored.

It'll not. TBH set_time_limit doesn't matter in the last script at all.

There must be another reason why the script is aborted.

I'm not familiar with LiteSpeed, but from what I've gathered there is an option in server configuration to kill script when client aborts connection. Original script was flawed so we cannot tell for sure if connection_status returned wrong value and script looped indefinitely or script was killed as soon as connection was closed. Maybe Litespeed is also checking if process is sleeping and because of that it is killed. Any of that is only my speculation.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

hi,
the process is not killed when I click stop

ignore_user_abort(true);
set_time_limit(0);
error_log('start');
while(1)
{
    echo "\n";
    ob_flush();
    flush();

    // Did the connection fail?
    if(connection_status() != CONNECTION_NORMAL)
    {
        break;
    }

    sleep(5);
	error_log('loop, status: ' . connection_status());
}
error_log('stop');
[15-Dec-2022 15:28:54 UTC] start
[15-Dec-2022 15:28:59 UTC] loop, status: 0
[15-Dec-2022 15:29:04 UTC] loop, status: 0
[15-Dec-2022 15:29:09 UTC] loop, status: 0
[15-Dec-2022 15:29:14 UTC] loop, status: 0
[15-Dec-2022 15:29:19 UTC] loop, status: 0
[15-Dec-2022 15:29:24 UTC] loop, status: 0
[15-Dec-2022 15:29:29 UTC] loop, status: 0
[15-Dec-2022 15:29:34 UTC] loop, status: 0
[15-Dec-2022 15:29:39 UTC] loop, status: 0

@KapitanOczywisty
Copy link

What sapi is php running? var_dump(php_sapi_name());

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

What sapi is php running? var_dump(php_sapi_name());

its the same server

Server API : LiteSpeed V8.1 Cloudlinux 1.3

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

I just tested on another server that I ask access to do this test and the problem was the same but it does not have PHP 8 available.
(PHP Version 7.4.33, SAPI FPM/FastCGI)
I will try to get access to others servers to test this.

@stramunin
Copy link

I think the problem may be elsewhere, because you tried php-fpm.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

I published this for testing.
Server: PHP Version 8.1.13, LiteSpeed V8.1 Cloudlinux 1.3
(the log will be saved by ip to avoid conflicts)

https://00351.net/test.php

<?php
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

ini_set("error_log", __DIR__ . '/error_log-' . $ip);


ignore_user_abort(true);
set_time_limit(0);
error_log('start PHP ' . phpversion() . ' - SAPI ' . php_sapi_name());
$i = 0;
for ($i = 0; $i < 10; $i++) {
    echo str_repeat("\n", 5000);
    ob_flush();
    flush();

    // Did the connection fail?
    if (connection_status() != CONNECTION_NORMAL) {
        error_log('break!');
        break;
    }

    sleep(1);
    error_log('loop ' . $i . ', status: ' . connection_status());
}
error_log('stop');
echo 'stop!';

https://00351.net/log.php

<?php
if (isset($_GET['phpinfo'])) {
    echo 'phpinfo';
    echo phpinfo();
}


if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

ini_set("error_log", __DIR__ . '/error_log-' . $ip);

echo 'error_log=', ini_get('error_log'), '<br>';
if (file_exists('error_log-' . $ip))
    echo str_replace("\n", '<br>', file_get_contents('error_log-' . $ip));

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

PS: this host account is empty, there is no php.ini or any other files

image

@stramunin
Copy link

Sorry, but I'm afraid to follow unfamiliar links. :)

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

Not sure what demoniac virus you can catch just opening the link but sure, i'm just providing whatever I can to help understand the problem and for future reference the code provided may help.
If it works on some cases there must be a difference somewhere
And the "host is empty" message was not to say "its safe click here muahaha", the point was to say there is no external files changing php settings or whatever else may cause the problem

@stramunin
Copy link

I understand you.
I wanted to clarify the points that we know:

  • not working with LiteSpeed V8.1 Cloudlinux 1.3
  • not working with PHP Version 7.4.33, SAPI FPM/FastCGI

Right?

@KapitanOczywisty
Copy link

@seltix5 Litespeed is behind nginx, and that complicates things. Sending one character (echo "\n";) may not be enough to overflow the nginx proxy buffer (if is enabled) or it's not aborting internal connection when client disconnects. You can try to send more characters in loop (like 4k or more), but this is not looking like php issue and we won't be able to help much further.

@gwanglst
Copy link
Contributor

When PHP engine is not embedded in a web server, like LiteSpeed and FPM, it communicates with web server over an IPC connection, not directly associated with client connection, the connection_status is the status of the IPC connection.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

@seltix5 Litespeed is behind nginx, and that complicates things. Sending one character (echo "\n";) may not be enough to overflow the nginx proxy buffer (if is enabled) or it's not aborting internal connection when client disconnects. You can try to send more characters in loop (like 4k or more), but this is not looking like php issue and we won't be able to help much further.

hi, I try with 5k (code updated #10106 (comment)) but did not work either.

there is no solution for this then? :(

@KapitanOczywisty
Copy link

I've installed LiteSpeed V8.0.1 on docker and connection_status() works as expected, so this is an issue with nginx reverse proxy. You could contact hosting provider, they probably can tweak some nginx settings.

@seltix5
Copy link
Author

seltix5 commented Dec 15, 2022

I will try, hopefully they may know what setting is causing the problem.

@stramunin
Copy link

With nginx+php-fpm everything works.

@seltix5
Copy link
Author

seltix5 commented Dec 19, 2022

They finally make it work on the server after changing the PHP handler from LSAPI to suPHP.
I dont really understand what that trully means, I'm just reporting.
Why connection_status() does not work with LSAPI? Is this expected or is something else on the handler settings?

(PHP 7.4.33 - SAPI cgi-fcgi)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants