-
Notifications
You must be signed in to change notification settings - Fork 62
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
fix: handle client disconnect properly with ignore_user_abort true #207
fix: handle client disconnect properly with ignore_user_abort true #207
Conversation
7ae9f26
to
1df4a84
Compare
Codecov Report
@@ Coverage Diff @@
## master #207 +/- ##
============================================
- Coverage 94.50% 94.40% -0.11%
- Complexity 256 258 +2
============================================
Files 15 15
Lines 873 875 +2
============================================
+ Hits 825 826 +1
- Misses 48 49 +1
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
Hi, any news on this one? Thanks! |
Why hasn't it been merged yet? This commit fixed all my problems with streaming and downloads |
@staabm could you please have a look at the PR? Thanks a lot! :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great thanks - verified the test locally.
@phil-davis do you have an idea on the cs error on php7.4 only? |
ignore_user_abort(true) instruct php to not abort the script on client disconnect. To avoid reading the entire stream and dismissing the data afterward, check between the chunks if the client is still there. Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
1df4a84
to
f2a1635
Compare
I fixed CI with PR #208 and then rebased here. |
And pushed a small change to get |
// Abort on client disconnect. | ||
// With ignore_user_abort(true), the script is not aborted on client disconnect. | ||
// To avoid reading the entire stream and dismissing the data afterward, check between the chunks if the client is still there. | ||
if (1 === ignore_user_abort() && 1 === connection_aborted()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.php.net/manual/en/function.ignore-user-abort.php
This PHP function does return an int
- looking at its name, I would have assumed it returned a bool
!
So this code does look OK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the same experience ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just figured, I should cover this better in PHPStan: phpstan/phpstan-src#2489
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also connection_aborted
impurity will be covered by phpstan/phpstan-src#2555
awesome, thanks phil. |
I will sort out backporting this (and any other recent fixes) to the 6.x and 5.x release series.
|
This fix is now available in 5.1.7 6.0.1 and 7.0.1 |
This should be reopened, 27.0.1 did not fix the issue. Nextcloud keeps downloading full files even after canceling the file download. Just try to download a 100gb file and cancelling it immediately. You can execute this command to check it out:
|
I bet you are not using the patched version. |
Sorry I jumped here from a linked nextcloud issue instead of nextcloud repo! haha, they have not fixed the issue, not sabre! |
Np, I am the one who linked the PR to that issue. |
The issue is fixed with Nextcloud 28 which is not released yet. |
// Abort on client disconnect. | ||
// With ignore_user_abort(true), the script is not aborted on client disconnect. | ||
// To avoid reading the entire stream and dismissing the data afterward, check between the chunks if the client is still there. | ||
if (1 === ignore_user_abort() && 1 === connection_aborted()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd assume 0 means false and 1 is true?
If so, this code falsely breaks when the connection was aborted AND we want to ignore that?
Or did i mix something up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.php.net/manual/en/function.ignore-user-abort.php
1 === ignore_user_abort()
means "ignore user abort has been enabled" (somewhere in "the system" or "the code" prior to this point)
1 === connection_aborted()
means that a connection has "gone away".
When these 2 things both happen, we are deciding, for this "manual" stream-copy loop, we do want to stop feeding the stream copy (even though "the system" has enabed ignore_user_abort()
). Because we know that it is pointless to keep looping and pushing out chunk-size bytes each time.
If the system setting is ignored (ignore_user_abort) why is it even checked? It should abort in both cases and with just1 === connection_aborted() is not enough? It is aborted automatically if system setting is enabled? |
That is probably correct. But the extra check is not going to break anything (or cause any different behavior, IMO!). So I guess we leave the code as it is. |
I've checked out these fixes are working on my instance. But they don't make any changes in the case of link-sharing. My Nextcloud does not stop reading the file when accessed via a public link. |
IMO the PR only works with chunked requests or range requests. How do your http requests look like? |
#205 but with tests ;)
ignore_user_abort(true) instruct php to not abort the script on client disconnect. To avoid reading the entire stream and dismissing the data afterward, check between the chunks if the client is still there.