@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove the execution time limit (if any) before sinking HTTP responses

Summary:
Ref T12907. At least part of the problem is that we can hit PHP's `max_execution_time` limit on the file download pathway.

We don't currently set this to anything in the application itself, but PHP often sets it to 30s by default (and we have it set to 30s in production).

When writing responses, remove this limit. This limit is mostly a protection against accidental loops/recurison/etc., not a process slot protection. It doesn't really protect process slots anyway, since it doesn't start counting until the request starts executing, so you can (by default) //send// the request as slowly as you want without hitting this limit.

By releasing the limit this late, hopefully all the loops and recursion issues have already been caught and we're left with mostly smooth sailing.

We already remove this limit when sending `git clone` responses in `DiffusionServeController` and nothing has blown up. This affects `git clone http://` and similar.

(I may have had this turned off locally and/or just be too impatient to wait 30s, which is why I haven't caught this previously.)

Test Plan:
- Poked around and downloaded some files.
- Will `curl ...` in production and see if that goes better.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T12907

Differential Revision: https://secure.phabricator.com/D19547

+27 -1
+10 -1
src/aphront/response/AphrontResponse.php
··· 54 54 55 55 56 56 public function getContentIterator() { 57 - return array($this->buildResponseString()); 57 + // By default, make sure responses are truly returning a string, not some 58 + // kind of object that behaves like a string. 59 + 60 + // We're going to remove the execution time limit before dumping the 61 + // response into the sink, and want any rendering that's going to occur 62 + // to happen BEFORE we release the limit. 63 + 64 + return array( 65 + (string)$this->buildResponseString(), 66 + ); 58 67 } 59 68 60 69 public function buildResponseString() {
+17
src/aphront/sink/AphrontHTTPSink.php
··· 112 112 $response->getHTTPResponseMessage()); 113 113 $this->writeHeaders($all_headers); 114 114 115 + // Allow clients an unlimited amount of time to download the response. 116 + 117 + // This allows clients to perform a "slow loris" attack, where they 118 + // download a large response very slowly to tie up process slots. However, 119 + // concurrent connection limits and "RequestReadTimeout" already prevent 120 + // this attack. We could add our own minimum download rate here if we want 121 + // to make this easier to configure eventually. 122 + 123 + // For normal page responses, we've fully rendered the page into a string 124 + // already so all that's left is writing it to the client. 125 + 126 + // For unusual responses (like large file downloads) we may still be doing 127 + // some meaningful work, but in theory that work is intrinsic to streaming 128 + // the response. 129 + 130 + set_time_limit(0); 131 + 115 132 $abort = false; 116 133 foreach ($data as $block) { 117 134 if (!$this->isWritable()) {