2026/03/25

From WoozleCodes
< 2026 | 03
Jump to navigation Jump to search
Wednesday, March 25, 2026 (#84)
Tuesday Wednesday Thursday posts:prev <this> next

References

Manual Coarse-Grained Step-Through Debugging

  • [Schema]::EnsureSchema():
    • $oEngine = $this->OEngine();
    • $oClient = $oEngine->OClient();
    • (in "if" clause) $oClient->SchemaExists($sSchema) -- this is why we need the schema-list
    • [Client]::SchemaExists() eventually ends up at [Client]::NewSchemaList() (first time through, anyway):
      • $oCmd = CmdLineClass::FromString($oSyntax->ListSchemas());
      • $oCmd->QORunner()->CopyIt($qoRun);
      • $oCSListen = new BufferClass;
      • $oCmd->QOListener()->SetIt($oCSListen);
      • $oCSErrors = new ScrnErrsClass;
      • $oCmd->QOErrorBin()->SetIt($oCSErrors);
      • if ($qoRun->HasIt()) {
             $oRSLecture = $qoRun->GetIt()->OLecture();
             UpdateClass::FromEngine($this->OEngine(),$oRSLecture);
             #$this->AmHere('SET UPDATER '.UpdateClass::class.' on '.get_class($oRSLecture));
             $oRSLecture->AmHere('<- LECTURE OBJECT');
             $qoRun->GetIt()->OListen()->AmHere('<- LISTEN OBJECT');
        }
        if ($inSeq) {
            // keeping process open -- just send commands directly
            $oRun = $this->QORunner()->GetIt();
        } else {
            // this is a one-shot -- send commands through the filter-chain
            $oRun = $oServer;
        }
        $oActCmd = $oRun->DoCommand($oCmd);
        $oRun = $oCmd->QORunner()->GetIt();
        $oRun->DoInOutLoop();
        
      • [Runner]::DoInOutLoop():
        • while ($doLoop) {
          • $oOpNew = $oCanals->ConveyCheck();
          • [Canals]::ConveyCheck():
            • Currently has 2 Canals to iterate through (what happened to #3, Errors?):
              • 1: id=5374 (proc stdout) process stream ⇒ id=5388 buffer stream
              • 2: (we don't get to this one)

Diving into that next-to-last item:

[Canal #1, $oSrce is 5374 ⇒ $oDest is 5388]->ConveyCheck() ⇒ ->ConveyNow():
  • $qoUpd = $oSrce->QOUpdater();
  • $doILoop = $ok = $oSrce->HasMore();
  • while ($doILoop) { // while there's input to process --
    • if (empty($sGot)) { // if buffer is empty --
      • $oGot = $oSrce->PullBytes(self::IBUFF_SIZE);
      • $qoUpd->OnIterate();

The problem here is that the Updater object ($qoUpdate->GetIt()) is not set, so $qoUpd->OnIterate() doesn't do anything.

Look back through the trace to find where it was supposed to be set, what I find instead is a tangle of different Stream-objects. I think I need a dramatis personae. Looking at the various items that show up in the debugging output:

  • 5374 (proc stdout) process stream ( ⇒ id=5388 buffer stream )
  • 5388 buffer stream (receives from 5374 proc stdout); set up as LISTEN in the Client, does have an Updater
  • 5389 a SRCE Exec Stream in a Conveyer, apparently sending to 5388, does not have an Updater

What I'm seeing here is that at one point it was 5374⇒5388, but then later it seems to be 5389⇒5388. Wot do be hopnin heer.

  • Even if it's somehow ok for 5374 to be replaced by 5389, we need an Updater on whichever one of those is being used.

10:17

I added caching of the Stream objects in [WFe]IO\Aspect\Connx\aux\A\caPool because it seemed possible that the overwriting was happening there (creating a new Stream instead of retrieving an existing one), and now all the object IDs are renumbered. ...but! The end result is that a Stream that did not have an Updater now has one. Check and see if anything is working better? (i.e. remove die())

10:55

Although it still gets stuck, we do at least have on-screen updates now -- so I can use that as my debug viewer instead.

12:12

More to the point, the Updater is supposed to invoke the code which contextually determines if we've received what we need, and then sets the flags for EoF -- which I haven't written yet because I need to try some things and see what works.

12:52

The problem now is retrieving the correct Stream for the Engine to look at when CheckStream() is called. I keep thinking I'm passing it the Listener buffer (which accumulates all data received -- I'm hoping there will be something obvious like a pair of CRLFs or newlines at the end), but what I get is an Exec stream...

The current dramatis personae, in ID order:

  • 5358 [WFe]\IO\Aspect\Connx\Stream\Native\cExec (LISTEN in Proc i.e. $oRun)
  • 5361 - process stream: stdout - [WFe]\IO\Aspect\Connx\Stream\Native\cExec (SRCE in Conveyer)
    • ⇒ id5391 buffer stream
  • 5365 - process stream: stderr
    • ⇒ id5374 screen
  • 5374 - screen
    • ⇐ id5365 process stream: stderr
  • 5391 [WFe]\IO\Aspect\Connx\Stream\Finite\cBuffer (LISTEN in Client i.e. $this, DEST in Conveyer)
    • ⇐ id5361 process stream: stdout

...so, yeah, what's happening to id5358? What is it supposed to be listening to?

13:18

id5358 is $oCSListen:

  • $oCSListen = new BufferClass;
  • $oCmd->QOListener()->SetIt($oCSListen);

...argh, the numbers keep changing...

(I'd be tempted to try to add some kind of enumeration-feature to Ferreteria classes (call it FOID, for Ferreteria Object ID), but I don't think there's any quick way to be sure that the counter-code will be executed. I'd have to start throwing errors whenever an FOID was requested but hasn't been set... oh but wait, here's a thought: assign the numbers at request time, if not already set...)

20:05

That turned out to be easy, actually -- I replaced this code in [WFe]Sys\Diag\Util\tHelper:

public function ObjectID() : int { return spl_object_id($this); }

...with this:

private static $idFO_Next = 0;
private $idFO = NULL;
public function ObjectID() : int { return is_int($this->idFO) ? $this->idFO : ($this->idFO = self::$idFO_Next++) ; }

20:34

So, once again, the dramatis personae but with IDs that will hopefully be a little less mutable (as long as I don't change the order in which I first access the IDs, anyway):

  • 1 [WFe]\IO\Aspect\Connx\Stream\Finite\cBuffer->NewSchemaList() : <= LISTEN (in Client); Cmd Listener; ConveyNow() DEST
  • 2 [WFe]\IO\Aspect\Connx\Stream\Native\cExec->NewSchemaList() : <- LISTEN OBJECT (in Conveyer)
  • 3 process stream: stdout; ConveyNow() SRCE
    • ⇒ 1 buffer stream
  • 5 process stream: stderr
    • ⇒ 6 screen
  • 6 screen
    • ⇐ 5 process stream: stderr

Non-streams:

  • 4 [WFe]\IO\Aspect\Connx\cConveyer connecting id3 => id1
  • 7 [WFe]\IO\Aspect\Connx\cConveyer connecting id5 => id6
  • 8 [WFe]\IO\Aspect\Connx\aux\A\cCanals checking canal connecting id3 => id1

...now, what was I trying to figure out again? 🤔

22:27

The stream the Updater has ended up with is id3 -- but I think what we want is id1, the Listener memory-buffer.