Page MenuHomePhabricator

Enable phpdbg on mwdebug* servers
Closed, ResolvedPublic

Description

phpdbg is a command line debugger similar in purpose to gdb or hhvm -m debug. There are some bugs (particularly cross-wiki interactions in my case), that can take significant time to reproduce locally, but can be fairly easily reproduced using read-only API calls. When we had hhvm deployed I would spin up hhvm -m debug, create a RequestContext, FauxRequest, and ApiMain, and then execute ApiMain with breakpoints set. phpdbg isn't quite as full featured as the hhvm debugger, hhvm offered a combined debugger+php repl, whereas phpdbg only provides the debugger and runs plain php scripts, but I think we could get most of the way there. Perhaps even a wrapper could be included to transform an external url into the appropriate RequestContext/FauxRequest/ApiMain invocation.

Event Timeline

In terms of actual deployment I think we can simply install the php-phpdbg package (available from our php7.2 deb component) and adjust MWScript.php to allow the 'phpdbg' SAPI in addition to the 'cli' SAPI that it currently allows.

Change 573333 had a related patch set uploaded (by Hnowlan; owner: Hnowlan):
[operations/puppet@production] mediawiki: install phpdbg on mwdebg hosts.

https://gerrit.wikimedia.org/r/573333

Change 573558 had a related patch set uploaded (by Hnowlan; owner: Hnowlan):
[operations/mediawiki-config@master] MWScript: Allow MWScript to be invoked via the debugger

https://gerrit.wikimedia.org/r/573558

Change 573333 merged by Hnowlan:
[operations/puppet@production] mediawiki: install phpdbg on mwdebg hosts.

https://gerrit.wikimedia.org/r/573333

Change 573558 merged by jenkins-bot:
[operations/mediawiki-config@master] MWScript: Allow MWScript to be invoked via phpdbg as well as the cli

https://gerrit.wikimedia.org/r/573558

Mentioned in SAL (#wikimedia-operations) [2020-03-05T10:48:34Z] <hnowlan@deploy1001> Synchronized multiversion/MWScript.php: T244549: enable running MWScript with phpdbg (duration: 01m 04s)

I'm sure this could be further improved, but in general it works!

ebernhardson@mwdebug1002:~$ cat test.php
<?php

require_once "$IP/maintenance/commandLine.inc";

parse_str('generator=search&piprop=thumbnail&coprop=type%7Cdim&pithumbsize=240&pilimit=50&action=query&ppprop=displaytitle&gsrlimit=50&format=json&colimit=50&gsrsearch=nearcoord:40075000m,48.866,2.314&cirrusIncLinkssW=1000&prop=coordinates%7Cpageimages%7Cdescription%7Cpageprops', $params);

$ctx = new RequestContext();
$ctx->setRequest(new FauxRequest($params));
$api = new ApiMain($ctx);
$api->execute();
var_dump($api->getResult()->serializeForApiResult());
ebernhardson@mwdebug1002:~$ PHP=phpdbg7.2 mwscript ../../../home/ebernhardson/test.php --wiki=testwiki                                                                    
[Welcome to phpdbg, the interactive PHP debugger, v0.5.0]                                                                                                                 
To get help using phpdbg type "help" and press enter
[Please report bugs to <http://bugs.php.net/report.php>]
[Successful compilation of /srv/mediawiki/multiversion/MWScript.php]
prompt> break CirrusSearch\Searcher::search
[Breakpoint #0 added at CirrusSearch\Searcher::search]
prompt> run
[Breakpoint #0 in CirrusSearch\Searcher::search() at /srv/mediawiki/php-1.35.0-wmf.22/extensions/CirrusSearch/includes/Searcher.php:187, hits: 1]
>00187:                 if ( $query->getDebugOptions()->isCirrusDumpQueryAST() ) {
 00188:                         return Status::newGood( [ 'ast' => $query->getParsedQuery()->toArray() ] );
 00189:                 }                       
prompt> ev var_dump($query->getParsedQuery()->toArray());
array(5) {
  ["query"]=>                                  
  string(32) "nearcoord:40075000m,48.866,2.314"
  ["rawQuery"]=>                                                                                                                                                            string(32) "nearcoord:40075000m,48.866,2.314"                                                                         
  ["queryClassCache"]=>
  array(1) {                
    [0]=>                                  
    string(13) "complex_query"
  }             
  ["featuresUsed"]=>                                 
  array(1) {               
    [0]=>                               
    string(9) "nearcoord"
  }
  ["root"]=> {verbose content clipped}
}
prompt>

Good to see. If there's more that can be done on my end please feel free to re-open, I was a little quick to close this one out.

Further improvements are probably not really an SRE thing. Essentially, use of ../../../home/ebernhardson/test.php, escaping the directories mwscript is trying to use, is probably at a minimum a bit of a hack. Additionally use of commandLine.incis likely discouraged, this is a BC wrapper that should go away some day, not be used by new things. I'll do some more testing with using shell.php together with phpdbg, debugging and interactive shell seems like the best place to end up at in the end.