Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pseudo-io writes fail for >= 256kB writes #99

Open
RootTJNII opened this issue Nov 20, 2019 · 6 comments
Open

Pseudo-io writes fail for >= 256kB writes #99

RootTJNII opened this issue Nov 20, 2019 · 6 comments

Comments

@RootTJNII
Copy link

RootTJNII commented Nov 20, 2019

When attempting to write >= 256kB of data I'm consistently seeing the connection hang. For the following code:

Net::SFTP.start(args) do |sftp|
  1024.times do |c|
    puts "Length: #{c}"
    sftp.file.open("test.file", "w") do |f|
      f.write(Random.new.bytes(c * 1024))
    end
  end
end

I see the following output:

[Snip <250]
Length: 250
Length: 251
Length: 252
Length: 253
Length: 254
Length: 255
Length: 256
[Upload hangs here, until killed with ctrl-c]
^CNoMethodError: undefined method `send_data' for nil:NilClass
from /home/tom/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:814:in `send_packet'
Caused by Interrupt:
from /home/tom/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/net-ssh-5.2.0/lib/net/ssh/connection/event_loop.rb:110:in `select'

The exception appears to be the same as #94.

@RootTJNII
Copy link
Author

upload! doesn't have this problem, working around it with a tempfile.

@dawidof
Copy link

dawidof commented Feb 12, 2021

@RootTJNII actually I got problem with upload!, it can be tempfile or stringIO

@dawidof
Copy link

dawidof commented Feb 16, 2021

Issue solved, connection was in class method, which was cached, moved the connection to instance method.

@mayuresh-srivastava
Copy link

I found the workaround as mentioned here

@acuster77
Copy link

acuster77 commented Jun 9, 2023

Ran into the same issue today.

Using ruby 3.1.3p185 with [email protected] and [email protected]. I'm using OpenSSH, which has a max packet size of 256kb which I suspect is the culprit:

https://github.com/openssh/openssh-portable/blob/2709809fd616a0991dc18e3a58dea10fb383c3f0/packet.c#LL106C1-L106C1

It doesn't seem like there is any logic for checking the size of the payload within the packet to be delivered to the server when using the write method.

I really wanted to avoid writing anything to disk and using upload as I needed to upload partial chunks of data at a time. This code is working for me:

string_io = StringIO.new(file_data)

Net::SFTP.start(*args) do |sftp|
  file_handle = sftp.open!("foo.bin", "wb+")
  # utilizes the configured max packet size, by default it's 32768 bytes
  max_packet_size = sftp.channel.local_maximum_packet_size
  offset = 0
  until string_io.eof?
    datum = string_io.read(max_packet_size)
    sftp.write!(file_handle, offset, datum)
    offset += datum.bytesize
  end
end

@prcongithub
Copy link

@acuster77 Your solution worked in my case. Thanks for this.

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

No branches or pull requests

5 participants