2026/09/20
< 2026
|
Sunday, September 20, 2026 (#263)
|
|
References |
Main Work
After the main rework of Ferreteria connection-sessions, I'm still trying to figure out why each schema-export opens more streams than it closes (leading to an eventual crash when we run out of stream-slots).
The problem seems to come down to this:
- Process-streams can't be opened/closed the same way as other streams. (For local processes, they're created by
proc_open(); for ssh streams, they're created byssh2_fetch_stream().) - I therefore needed to allow the Stream\Rsrc class to optionally accept already-open stream-resources, and not attempt to open or shut them.
- This also means that the caller needs to be responsible for closing them.
- Figuring out where this is supposed to happen (but is not) has been (and is continuing to be) tricky.
- There was also some uncertainty at first about the proper method of closing them; apparently
fclose()is fine. - It's also not clear whether they should be closed when I'm not closing the connection (this only matters in ssh2). The problem with leaving them open has been that the object decides, for some reason, that they aren't open, and opens new ones. This in turn may be because we're somehow getting a new connection object, which shouldn't be happening (but I haven't solidly confirmed this yet; I just see the object ID of the stream-opener changing for each schema, but I'm not yet sure which object that is).
- There was also some uncertainty at first about the proper method of closing them; apparently
- 09:25 Confirmed that what's opening new streams is
Sys\InOut\Connx\Server\Process\ssh2\Native, and that this is somehow a new object each time (oid: 63, 83, 103...).- ...but how/why are we getting a new object for that, each time?
- 09:45 Kind of a retroactive "duhhh" -- especially since I've repeatedly worked this out in my head: for exports, we need a new "dump" command each time. (This means we need a new connection -- which boils down to creating a new Session object, which then creates/manages the connection.)
- So maybe the problem is that the previous connection isn't being shut properly? Checking on that...
- 10:13 The Session object is being created but never opened or closed.
- It would be easy enough to fix that -- but what it does is open and shut the connection -- which is apparently *already* being opened somewhere (otherwise ssh wouldn't work), so the net effect should be nil. The question then is: how/where is the connection being opened?
- 10:26 It's opened by
Session->DoCommand(). This gets the job done, but is it appropriate? Should we maybe require DoCommand()'s caller to open the Session first, so it's clear that it needs to be closed again afterwards?- That won't really work, though, because local proc can't actually open the Session without a command. On the other hand, we could still emulate that behavior --
ActualOpen()would set a flag, andDoCommand()would throw an error if the flag wasn't set.
- That won't really work, though, because local proc can't actually open the Session without a command. On the other hand, we could still emulate that behavior --
- 12:50 Options:
- Require Session to be open before DoCommand() is called (requires emulation in Local venue).
- Require a Command to be set before calling Open() (requires emulation in SSH venue).
- Somehow refactor DoCommand() into OpenCommand()/ShutCommand() (maybe have a NewCommmand(), which returns a Command-object that can be opened to execute and closed when finished; throws error if destructed before closing).
- ...or the Command-object could just close itself whenever
__destruct()ed...
- ...or the Command-object could just close itself whenever
- 16:03 Every solution so far seems to either not close the streams or else closes things too many times. (Is this sort of a Streams-garbage-collection issue?) I keep wondering if I'm (a) being too persnickety about disallowing too-many-closes or if I'm being sloppy about how opening & closing are handled and this is just highlighting that (without making it at all easy to fix).
- ...but okay, to be fair I only tried a variant on the 3rd solution; I haven't tried the others. Let's go that route, then.
- 17:23 I started trying to eliminate Session entirely, because it seemed like it was just confusing things (having interactions with both Port and Proc) -- but what it legitimately does add is Stream-management, including the I/O loop.
- So I think the thing to do is get rid of its connection to Proc, and have it go entirely through Port.
- 22:07 ...except that Session needs to talk to Proc in order to get the process-streams. So... never mind that; I guess Session is the best model it can be, aside from changing how starter-commands are invoked.