LibSshNet Help

Session Timeouts

Session timeouts control how long SSH operations wait before giving up. This is different from keepalives - timeouts prevent operations from hanging indefinitely, while keepalives prevent idle connections from being closed.

Understanding Timeouts

By default, libssh2 has no timeout - operations will wait indefinitely until they complete or fail. Setting a timeout ensures operations don't hang forever.

using NullOpsDevs.LibSsh; using NullOpsDevs.LibSsh.Credentials; var session = new SshSession(); session.Connect("example.com", 22); // Set a 30-second timeout for all operations session.SetSessionTimeout(TimeSpan.FromSeconds(30)); session.Authenticate(SshCredential.FromPassword("user", "password")); // All subsequent operations will timeout after 30 seconds var result = session.ExecuteCommand("some-command");

Socket Timeout vs Session Timeout

NullOpsDevs.LibSsh provides two types of timeouts that serve different purposes:

Socket Timeout

Socket timeout controls the low-level TCP network operations (send and receive). This is configured during connection:

var session = new SshSession(); // Set socket timeout to 10 seconds - affects TCP send/receive operations session.Connect("example.com", 22, socketTimeout: TimeSpan.FromSeconds(10)); // Socket timeout is now active for all network I/O session.Authenticate(credential);

Key characteristics:

  • Set during Connect() or ConnectAsync()

  • Affects underlying TCP socket send and receive operations

  • Default: No timeout (infinite) if not specified

  • Cannot be changed after connection is established

  • Controls how long the socket waits for network data

Session Timeout

Session timeout controls SSH protocol operations (commands, file transfers, authentication). This is configured after connection:

var session = new SshSession(); session.Connect("example.com", 22); // Set session timeout to 5 minutes - affects SSH operations session.SetSessionTimeout(TimeSpan.FromMinutes(5)); session.Authenticate(credential); // This command will timeout if SSH operation takes longer than 5 minutes var result = session.ExecuteCommand("long-running-command");

Key characteristics:

  • Set after Connect() using SetSessionTimeout()

  • Affects SSH protocol operations (commands, authentication, file transfers)

  • Default: No timeout (infinite)

  • Can be changed at any time after connection

  • Controls how long SSH operations wait before giving up

Comparison Table

Feature

Socket Timeout

Session Timeout

Layer

TCP/Network

SSH Protocol

When set

During Connect()

After Connect()

Controls

TCP send/receive operations

SSH operations (commands, transfers)

Default

No timeout (infinite)

No timeout (infinite)

Can change

No (fixed at connection)

Yes (anytime)

Configuration

Connect(host, port, socketTimeout)

SetSessionTimeout()/DisableSessionTimeout()

Use case

Prevent network I/O hangs

Prevent SSH operation hangs

When to use

Only when facing network timeout issues

For general operation timeout control

Using Both Together

For comprehensive timeout protection in problematic network environments, use both:

var session = new SshSession(); // Socket timeout: Only set if experiencing network-level hangs session.Connect("example.com", 22, socketTimeout: TimeSpan.FromSeconds(30)); // Session timeout: Prevent SSH operations from hanging session.SetSessionTimeout(TimeSpan.FromMinutes(5)); session.Authenticate(credential); // Now protected at both network and SSH protocol layers var result = session.ExecuteCommand("some-command");

When to use each:

  • Socket timeout: Only when you are facing network-level timeout problems (e.g., extremely slow networks, network infrastructure that causes hangs at the TCP level)

  • Session timeout: Use for general operation timeout control (e.g., long-running commands, large file transfers)

  • Both: Only in production environments with known network issues

Setting a Timeout

Configure the timeout after connecting but before or after authenticating:

var session = new SshSession(); session.Connect("example.com", 22); // Set a 2-minute timeout session.SetSessionTimeout(TimeSpan.FromMinutes(2)); session.Authenticate(credential); // This command will timeout if it takes longer than 2 minutes try { var result = session.ExecuteCommand("long-running-command"); Console.WriteLine(result.Stdout); } catch (SshException ex) when (ex.Error == SshError.Timeout) { Console.WriteLine("Command timed out after 2 minutes"); }

Disabling Timeouts

To restore the default behavior (wait indefinitely):

// Disable timeout - operations will wait forever session.DisableSessionTimeout(); // This command will never timeout var result = session.ExecuteCommand("very-long-command");

When to Use Timeouts

Use Timeouts When:

  1. Executing commands that might hang

    session.SetSessionTimeout(TimeSpan.FromMinutes(5)); var result = session.ExecuteCommand("./unpredictable-script.sh");
  2. Transferring large files

    session.SetSessionTimeout(TimeSpan.FromMinutes(30)); using var stream = File.OpenRead("large-file.zip"); session.WriteFile("/remote/path/large-file.zip", stream);
  3. In production environments

    // Prevent operations from hanging indefinitely session.SetSessionTimeout(TimeSpan.FromMinutes(10));
  4. When connecting to unreliable servers

    session.Connect("unreliable-server.com", 22); session.SetSessionTimeout(TimeSpan.FromSeconds(30));

Don't Use Timeouts When:

  1. Running truly long operations - Use cancellation tokens instead

  2. In development - Let operations complete naturally to see actual behavior

  3. Operations are already bounded - If the command itself has a timeout

Timeout vs. Keepalive

These are different mechanisms with different purposes:

Feature

Session Timeout

Keepalive

Purpose

Prevent operations from hanging

Prevent idle disconnection

When active

During active operations

During idle periods

What it does

Aborts operation if too slow

Sends periodic messages

Error on failure

SshError.Timeout exception

Connection drops

Configuration

SetSessionTimeout()

ConfigureKeepAlive() + SendKeepAlive()

Using Both Together

For robust connection management, use both timeouts and keepalives:

var session = new SshSession(); session.Connect("example.com", 22); // Set operation timeout to 5 minutes session.SetSessionTimeout(TimeSpan.FromMinutes(5)); // Configure keepalive to send every 30 seconds when idle session.ConfigureKeepAlive(wantReply: false, interval: TimeSpan.FromSeconds(30)); session.Authenticate(credential); // Execute command with timeout protection var result = session.ExecuteCommand("some-command"); // When idle, manually send keepalives while (waiting) { Thread.Sleep(30_000); session.SendKeepAlive(); // Keep connection alive during idle }

Handling Timeout Errors

When an operation times out, you'll receive an SshException with SshError.Timeout:

try { session.SetSessionTimeout(TimeSpan.FromSeconds(10)); var result = session.ExecuteCommand("sleep 30"); // This will timeout } catch (SshException ex) when (ex.Error == SshError.Timeout) { Console.WriteLine("Operation timed out!"); Console.WriteLine("The command took too long to execute"); // Decide what to do: // - Retry with a longer timeout? // - Cancel the operation? // - Notify the user? } catch (SshException ex) { Console.WriteLine($"Other SSH error: {ex.Message}"); }

Timeout Scope

The timeout applies to blocking libssh2 operations, including:

  • Command execution (ExecuteCommand)

  • File transfers (ReadFile, WriteFile)

  • Authentication (Authenticate)

  • Keepalive messages (SendKeepAlive)

Best Practices

  1. Set reasonable timeouts:

    • Too short: Operations fail unnecessarily

    • Too long: Hung operations waste resources

    • Typical: 1-5 minutes for most operations

  2. Adjust for operation type:

    // Short timeout for quick commands session.SetSessionTimeout(TimeSpan.FromSeconds(30)); var result = session.ExecuteCommand("whoami"); // Longer timeout for file transfers session.SetSessionTimeout(TimeSpan.FromMinutes(30)); session.WriteFile("/path/large.zip", stream);
  3. Consider network conditions:

    • Slower networks need longer timeouts

    • High-latency connections need more time

    • Unreliable networks may need retries

  4. Log timeout events:

    try { var result = session.ExecuteCommand(command); } catch (SshException ex) when (ex.Error == SshError.Timeout) { logger.LogWarning($"Command timed out: {command}"); throw; }
  5. Use cancellation tokens for long operations:

    // Prefer cancellation tokens for user-initiated cancellation using var cts = new CancellationTokenSource(); var result = await session.ExecuteCommandAsync(command, cancellationToken: cts.Token);

Example: Configuring for Different Environments

public class SshConnectionManager { public SshSession CreateSession(string environment) { var session = new SshSession(); session.Connect(GetHostForEnvironment(environment), 22); // Configure based on environment switch (environment) { case "development": // No timeout in dev - let things run session.DisableSessionTimeout(); break; case "staging": // Moderate timeout for staging session.SetSessionTimeout(TimeSpan.FromMinutes(10)); break; case "production": // Strict timeout in production session.SetSessionTimeout(TimeSpan.FromMinutes(5)); session.ConfigureKeepAlive(false, TimeSpan.FromSeconds(30)); break; } return session; } private string GetHostForEnvironment(string env) => env switch { "development" => "dev-server.local", "staging" => "staging-server.example.com", "production" => "prod-server.example.com", _ => throw new ArgumentException($"Unknown environment: {env}") }; }

See Also

  • SshSession.SetSessionTimeout() (SshSession.cs:276) - Set operation timeout

  • SshSession.DisableSessionTimeout() (SshSession.cs:259) - Disable timeout

  • Keeping Connection Alive - Prevent idle disconnections

  • Error Handling - Handling timeout errors

03 November 2025