2026/03/25

From Woozle Writes Code
< 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 53745388, but then later it seems to be 53895388. 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.