fieldrndservices / libssh2-labview

A LabVIEW library for SSH client support via libssh2
Apache License 2.0
22 stars 2 forks source link

Read All and Read All stderr don't work together #67

Open keinstein opened 6 months ago

keinstein commented 6 months ago

Neither Read All nor Read All stderr work reliably. The situation gets even worse when I tried to combine both VIs to read all output of a batch command like:

(sleep 1 ; cat large-file-1 ; sleep 5 ; cat large-file-2 ; sleep 10) & (sleep 2 ; cat large-file-3 ; sleep 4; cat large-file-4  ) >&2

I solved this problem for my company in the following way:

  1. patch Read and Write to return the libssh2lv return value.
  2. Add a modified VI named “Read All both” that poll both channels in a loop by calling “Read” and “Read stderr” in sequence each iteration until both libssha2lv return values are zero.
  3. If both VIs return EAGAIN, or if one returns EAGAIN and the other has returned zero in the past, sleep for some small time
  4. As an optimisation I skip calling Read if it already returned zero. For that I use shift registers.
  5. The VI returns both the collected stdout and stderr
  6. I call the VI in non-blocking mode.

I also tried to use “Read All” and “Read All stderr” in blocking mode but this doesn't seem to work. Parallel reads seem to confuse libSSH2 (if I'm not mistaken), serial reads seem to destroy the buffers of the other stream, too. So either stderr or stdout can be retrieved, but not both of them.

volks73 commented 6 months ago

The Read All VIs are not very sophisticated. They are reading all of the buffer internal to libssh2, not continuously reading all of the output from the server. Your resolution sounds like how a more full-featured "shell" is supposed to be implemented using the VIs and functions of the underlying libssh2 library. This toolkit is a thin wrapper around the libssh2 library and relatively "low level". The intention is for more feature full abstractions to be created on top of this library, like you have done.

Are you able to share your implementation as I imagine others would be grateful for the example and guidance? Even just a VI snippet would be greatly appreciated.

Is the Read-Execute-Print-Loop with a Raspberry Pi example similar to your implementation/use case? I added "Raspberry Pi" to the name because I was getting a lot of questions about interacting with Raspberry Pis, but the example is applicable to other targets.

keinstein commented 6 months ago

The major problem is:

  1. libssh2lv rewrites the return codes
  2. The labview code destroys the return codes so that it is difficult to to reconstruct the return code from LibSSH2: One part is returned in the error message one part is returned in the returned array. And some special code deals with EAGAIN (which means: E- call the function AGAIN).
  3. If You have a proper way that makes the above function work to return all data, and that is consistent with the current implementation, feel free to provide a better answer.

Fortunately libssh2lv changes only the values, but not the semantics of the return code of the underlying function used by the LabVIEW code.

The examples didn't help me in any way: As I already posted, I'm using an mixture of Read VIs. that pass the original uninterpreted return value from libSSH2 to the common Read All both VI.

This problem also affects both the Read All VI as well as the Read All stderr VI as both do not evaluate whether libssh2 returns 0. None of them honours EAGAIN.