0 votes
by (220 points)

Hello,
I use SshChannel.RequestExec for command execution and I have a question regarding the ExtendedDataReceived event synchronization.
Is there any way to ensure that stdErr is empty?
In the example below we synchronized 'ExtendedDataReceived' and 'return' via extDataLock, but, in my opinion, it is possible that return part will capture the lock first.

Task<(String StdOut, String StdErr, long ExitCode)>.Run(() =>
{
    ...
    // Get channel
    channel = _sshClient.Session.OpenSession();
    channel.ExtendedDataReceived += new EventHandler<SshExtendedDataReceivedEventArgs>((object sender, SshExtendedDataReceivedEventArgs e) =>
    {
        lock(extDataLock)
        {
            byte[] data = e.GetData();
            String resp = _sshClient.Encoding.GetString(data, 0, data.Length);
            stdErr.Append(resp);
        }
    });

    // Send command
    channel.RequestExec(Command);
    ...
    // Read responce
    byte[] buffer = new byte[4096];
    while (true)
    {
        if (!channel.Poll(some_timeout, SocketSelectMode.SelectRead))
            break;
        int n = channel.Receive(buffer, 0, buffer.Length);
        if (n <= 0)
            break;
        stdOut.Append(_sshClient.Encoding.GetString(buffer, 0, n));
        if (_tokenSource.Token.IsCancellationRequested)
            break;
    }
    ...
    // Close channel and get ExitCode
    if (channel != null)
    {
        channel.Close();
        SshChannelExitStatus exitStatus = channel.ExitStatus;
        if (exitStatus != null)
            exitCode = (int)exitStatus.ExitCode;
        channel.Dispose();
    }
    ...
    // Collect results and return
    // ISSUE: Empty StdErr because of late event ExtendedDataReceived
    lock(extDataLock)
    {
        return (StdOut: stdOut.ToString(), StdErr: stdErr.ToString(), ExitCode: exitCode);
    }
}, _tokenSource.Token);

1 Answer

0 votes
by (73.5k points)

Unfortunately, this is know limitation of the event approach.

We plan to address this issue in the next update of SSH core (scheduled for next year 2021).

You can workaround the issue by setting:

channel.ExtendedDataMode = SshChannelExtendedDataMode.TreatAsNormalData;

which causes the error data will be part of standard data.

If this is not acceptable solution for you, please let us know and describe what you want to achieve. Maybe, we can think of a different solution.

by (220 points)
Hello,
Unfortunately, it isn't acceptable for exec request to have mixed stdout and stderr. Separate stdout and stderr is one of the pros of Exec.
Please, let me know if there are some other solutions exept shell manipulations.
by (73.5k points)
I have sent you an email with link to a hotfix which should solve the issue.
by (220 points)
Hello,
I would like to revise old Rebex API issues. Could you check whether the fix for the current topic was released?
by (73.5k points)
Hello,
Yes, the hotfix using hidden (SshChannelExtendedDataMode)2 value is part of the main build. It is included from 2020 R4 version.
by (220 points)
Hello,
I apologize, I meant the regular solution, without hidden values. You mentioned that it was planned within the new SSH core.
by (73.5k points)
Unfortunately, the refactoring of the SSH core was postponed.
We were busy with other features, for complete list of changes you can see https://www.rebex.net/total-pack/history.aspx

I have added you to our internal mail list, we will contact you when this feature is implemented.
...