@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.

Let the top-level exception handler dump a stack trace if we reach debug mode before things go sideways

Summary:
Depends on D20140. Ref T13250. Currently, the top-level exception handler doesn't dump stacks because we might not be in debug mode, and we might double-extra-super fatal if we call `PhabricatorEnv:...` to try to figure out if we're in debug mode or not.

We can get around this by setting a flag on the Sink once we're able to confirm that we're in debug mode. Then it's okay for the top-level error handler to show traces.

There's still some small possibility that showing a trace could make us double-super-fatal since we have to call a little more code, but AphrontStackTraceView is pretty conservative about what it does and 99% of the time this is a huge improvement.

Test Plan: {F6205122}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13250

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

+91 -10
+2 -2
resources/celerity/map.php
··· 46 46 'rsrc/css/application/config/config-options.css' => '16c920ae', 47 47 'rsrc/css/application/config/config-template.css' => '20babf50', 48 48 'rsrc/css/application/config/setup-issue.css' => '5eed85b2', 49 - 'rsrc/css/application/config/unhandled-exception.css' => '9da8fdab', 49 + 'rsrc/css/application/config/unhandled-exception.css' => '9ecfc00d', 50 50 'rsrc/css/application/conpherence/color.css' => 'b17746b0', 51 51 'rsrc/css/application/conpherence/durable-column.css' => '2d57072b', 52 52 'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e', ··· 877 877 'syntax-highlighting-css' => '8a16f91b', 878 878 'tokens-css' => 'ce5a50bd', 879 879 'typeahead-browse-css' => 'b7ed02d2', 880 - 'unhandled-exception-css' => '9da8fdab', 880 + 'unhandled-exception-css' => '9ecfc00d', 881 881 ), 882 882 'requires' => array( 883 883 '01384686' => array(
+6
src/aphront/configuration/AphrontApplicationConfiguration.php
··· 118 118 $database_exception = $ex; 119 119 } 120 120 121 + // If we're in developer mode, set a flag so that top-level exception 122 + // handlers can add more information. 123 + if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) { 124 + $sink->setShowStackTraces(true); 125 + } 126 + 121 127 if ($database_exception) { 122 128 $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue( 123 129 $database_exception,
+41 -2
src/aphront/response/AphrontUnhandledExceptionResponse.php
··· 4 4 extends AphrontStandaloneHTMLResponse { 5 5 6 6 private $exception; 7 + private $showStackTraces; 7 8 8 - public function setException(Exception $exception) { 9 + public function setShowStackTraces($show_stack_traces) { 10 + $this->showStackTraces = $show_stack_traces; 11 + return $this; 12 + } 13 + 14 + public function getShowStackTraces() { 15 + return $this->showStackTraces; 16 + } 17 + 18 + public function setException($exception) { 19 + // NOTE: We accept an Exception or a Throwable. 20 + 9 21 // Log the exception unless it's specifically a silent malformed request 10 22 // exception. 11 23 ··· 61 73 $body = $ex->getMessage(); 62 74 $body = phutil_escape_html_newlines($body); 63 75 76 + $classes = array(); 77 + $classes[] = 'unhandled-exception-detail'; 78 + 79 + $stack = null; 80 + if ($this->getShowStackTraces()) { 81 + try { 82 + $stack = id(new AphrontStackTraceView()) 83 + ->setTrace($ex->getTrace()); 84 + 85 + $stack = hsprintf('%s', $stack); 86 + 87 + $stack = phutil_tag( 88 + 'div', 89 + array( 90 + 'class' => 'unhandled-exception-stack', 91 + ), 92 + $stack); 93 + 94 + $classes[] = 'unhandled-exception-with-stack'; 95 + } catch (Exception $trace_exception) { 96 + $stack = null; 97 + } catch (Throwable $trace_exception) { 98 + $stack = null; 99 + } 100 + } 101 + 64 102 return phutil_tag( 65 103 'div', 66 104 array( 67 - 'class' => 'unhandled-exception-detail', 105 + 'class' => implode(' ', $classes), 68 106 ), 69 107 array( 70 108 phutil_tag( ··· 79 117 'class' => 'unhandled-exception-body', 80 118 ), 81 119 $body), 120 + $stack, 82 121 )); 83 122 } 84 123
+11 -3
src/aphront/sink/AphrontHTTPSink.php
··· 5 5 * Normally this is just @{class:AphrontPHPHTTPSink}, which uses "echo" and 6 6 * "header()" to emit responses. 7 7 * 8 - * Mostly, this class allows us to do install security or metrics hooks in the 9 - * output pipeline. 10 - * 11 8 * @task write Writing Response Components 12 9 * @task emit Emitting the Response 13 10 */ 14 11 abstract class AphrontHTTPSink extends Phobject { 12 + 13 + private $showStackTraces = false; 14 + 15 + final public function setShowStackTraces($show_stack_traces) { 16 + $this->showStackTraces = $show_stack_traces; 17 + return $this; 18 + } 19 + 20 + final public function getShowStackTraces() { 21 + return $this->showStackTraces; 22 + } 15 23 16 24 17 25 /* -( Writing Response Components )---------------------------------------- */
-1
src/view/widget/AphrontStackTraceView.php
··· 10 10 } 11 11 12 12 public function render() { 13 - $user = $this->getUser(); 14 13 $trace = $this->trace; 15 14 16 15 $libraries = PhutilBootloader::getInstance()->getAllLibraries();
+1
webroot/index.php
··· 44 44 try { 45 45 $response = new AphrontUnhandledExceptionResponse(); 46 46 $response->setException($main_exception); 47 + $response->setShowStackTraces($sink->getShowStackTraces()); 47 48 48 49 PhabricatorStartup::endOutputCapture(); 49 50 $sink->writeResponse($response);
+30 -2
webroot/rsrc/css/application/config/unhandled-exception.css
··· 8 8 background: #fff; 9 9 border: 1px solid #c0392b; 10 10 border-radius: 3px; 11 - padding: 0 8px; 11 + padding: 8px; 12 12 } 13 13 14 14 .unhandled-exception-detail .unhandled-exception-title { 15 15 color: #c0392b; 16 - padding: 12px 8px; 16 + padding: 4px 8px 12px; 17 17 border-bottom: 1px solid #f4dddb; 18 18 font-size: 16px; 19 19 font-weight: 500; ··· 23 23 .unhandled-exception-detail .unhandled-exception-body { 24 24 padding: 16px 12px; 25 25 } 26 + 27 + .unhandled-exception-with-stack { 28 + max-width: 95%; 29 + } 30 + 31 + .unhandled-exception-stack { 32 + background: #fcfcfc; 33 + overflow-x: auto; 34 + overflow-y: hidden; 35 + } 36 + 37 + .unhandled-exception-stack table { 38 + border-spacing: 0; 39 + border-collapse: collapse; 40 + width: 100%; 41 + border: 1px solid #d7d7d7; 42 + } 43 + 44 + .unhandled-exception-stack th { 45 + background: #e7e7e7; 46 + border-bottom: 1px solid #d7d7d7; 47 + padding: 8px; 48 + } 49 + 50 + .unhandled-exception-stack td { 51 + padding: 4px 8px; 52 + white-space: nowrap; 53 + }