Skip to content

Deliver SSH events in the order libssh raises them - #15

Merged
plajjan merged 3 commits into
mainfrom
callback-order
Oct 9, 2026
Merged

plajjan merged 3 commits into
mainfrom
callback-order

Conversation

@plajjan

@plajjan plajjan commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

libssh dispatches inbound packets whenever one of its calls polls the socket, and acton-ssh makes such calls from inside Client and ServerSession methods as well as from the event loop. On the server, ssh_message_get in session_drive polls on every call, and on both sides the flush at the end of ssh_channel_write polls when a send left bytes buffered. A channel event raised inside one of those methods was sent while the session actor was the current actor, so it waited in that actor's outbox until the actor's message completed. If the worker went back to the event loop before then, the poll callback appended newer data straight to the receiver's mailbox and the older data arrived after it. Under load this reordered pipe streams, and NETCONF sessions saw a chunk header followed by bytes from a later message.

With this change every event is sent with no current actor, the way events raised from the event loop already were, so each one is appended to its receiver's mailbox when libssh raises it. All libssh calls for a session run on the thread that owns it, so each mailbox receives events in the order libssh raised them.

The new test runs eight pipes with pipelined three-write frames in both directions and checks every byte received. Without the change it failed 19 of 20 runs; with it, it passed 20 of 20.

libssh also dispatches inbound packets inside our Client and
ServerSession methods: ssh_message_get in session_drive and the flush
in ssh_channel_write both poll the socket. Events raised there waited
in the session actor's outbox until its message completed, and data
raised in the meantime from the event loop reached the receiver first,
so pipe streams arrived reordered under load.

Send every event with no current actor, so it is appended to the
receiver's mailbox when libssh raises it. Add a test that checks the
byte order of pipelined pipe traffic in both directions.
One run of the pipe order test takes longer than 10 s on the CI runners.
acton test shows a test's output only when it fails or times out, so the lines tell where a slow run spent its time.
@plajjan
plajjan merged commit 378a36a into main Oct 9, 2026
1 check passed
@plajjan
plajjan deleted the callback-order branch October 9, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant