From: Eric Hodel Date: 2006-03-24T15:58:46+09:00 Subject: Re: [ANN] socket_sendfile --Apple-Mail-4--479933733 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed On Mar 23, 2006, at 7:24 PM, ara.t.howard@noaa.gov wrote: > On Fri, 24 Mar 2006, Eric Hodel wrote: > >> == Using socket_sendfile >> >> require 'rubygems' >> require 'socket' >> require 'socket_sendfile' >> >> socket = TCPSocket.open host, port >> >> File.open 'myfile' do |fp| >> socket.sendfile fp >> end > > i'm just about to write a server which sends 1-3gb images as the > response... > this could be quite useful. > > one gripe. it doesn't work: > > /home/ahoward is insecure (40777), needs 0700 for perms. Exiting > > i work in a collaborative lab... all our home dirs are group > readable by > default. any way to adjust this? an env var perhaps? seems like > this should > just warn. That's RubyInline complaining. Let me check with Ryan Davis to see what can be done. > ok. one more issue: > > fortytwo :~/tmp > ruby ../a.rb > /usr/local/ruby-1.8.4/lib/ruby/gems/1.8/gems/RubyInline-3.4.0/./ > inline.rb:392: warning: Insecure world writable dir /usr/local, > mode 040777 > /usr/local/ruby-1.8.4/lib/ruby/gems/1.8/gems/ > socket_sendfile-1.1.0/lib/socket_sendfile.rb: In function > `bsock_sendfile': > /usr/local/ruby-1.8.4/lib/ruby/gems/1.8/gems/ > socket_sendfile-1.1.0/lib/socket_sendfile.rb:46: warning: implicit > declaration of function `sendfil > e' > /usr/local/ruby-1.8.4/lib/ruby/gems/1.8/gems/RubyInline-3.4.0/./ > inline.rb:396:in `build': error executing gcc -shared -Wall -W - > Wpointer-arith - > Wcast-qual -Wcast-align -Wwrite-strings -Wmissing-noreturn - > Werror -g -O2 -I /usr/local/ruby-1.8.4/lib/ruby/1.8/i686-linux -o / > home/ahoward/.rub > y_inline/Inline_BasicSocket_0a2b.so /home/ahoward/.ruby_inline/ > Inline_BasicSocket_0a2b.c : 256 (CompilationError) > Renamed /home/ahoward/.ruby_inline/Inline_BasicSocket_0a2b.c > to /home/ahoward/.ruby_inline/Inline_BasicSocket_0a2b.c.bad > from /usr/local/ > ruby-1.8.4/lib/ruby/gems/1.8/gems/RubyInline-3.4.0/./inline.rb: > 591:in `inline' > from /usr/local/ruby-1.8.4/lib/ruby/gems/1.8/gems/ > socket_sendfile-1.1.0/lib/socket_sendfile.rb:6 > from /usr/local/ruby-1.8.4/lib/ruby/site_ruby/1.8/ > rubygems/custom_require.rb:27:in `require' > from ../a.rb:3 > > > my system definitely has sendfile > > #include > > ssize_t sendfile(int out_fd, int in_fd, off_t *offset, > size_t count); > > > guess the signature won't cut it though eh? maybe i'll just have > to use dl? On FreeBSD it looks like this: #include #include #include int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); And has this to say about non-blocking sockets: When using a socket marked for non-blocking I/O, sendfile() may send fewer bytes than requested. In this case, the number of bytes success- fully written is returned in *sbytes (if specified), and the error EAGAIN is returned. Try this patch: --Apple-Mail-4--479933733 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="socket_sendfile.rb.linux.patch" Content-Disposition: attachment; filename=socket_sendfile.rb.linux.patch Index: lib/socket_sendfile.rb =================================================================== --- lib/socket_sendfile.rb (revision 8257) +++ lib/socket_sendfile.rb (working copy) @@ -4,9 +4,7 @@ class BasicSocket inline do |builder| - builder.include '' - builder.include '' - builder.include '' + builder.include '' builder.include '"ruby.h"' builder.include '"rubyio.h"' @@ -25,14 +23,9 @@ static VALUE bsock_sendfile(int argc, VALUE *argv, VALUE sock) { OpenFile *fptr, *sptr; VALUE io; - int fd, s, res; - off_t sent_bytes = 0; - size_t sent_total = 0; - struct timeval timeout; + int fd, s; + ssize_t sent_bytes; - timeout.tv_sec = 0; - timeout.tv_usec = 500; - rb_scan_args(argc, argv, "10", &io); GetOpenFile(io, fptr); @@ -41,23 +34,10 @@ GetOpenFile(sock, sptr); s = fileno(sptr->f); - for (;;) { - TRAP_BEG; - res = sendfile(fd, s, sent_total, 0, NULL, &sent_bytes, 0); - TRAP_END; + TRAP_BEG; + sent_bytes = sendfile(fd, s, 0, 0); + TRAP_END; - sent_total += sent_bytes; - - if (res == 0) - break; - - if (res < 0 && errno != EAGAIN) - rb_sys_fail("sendfile(2)"); - - // This socket is full, let's see if we can do work elsewhere. - rb_thread_select(0, NULL, NULL, NULL, &timeout); - } - return INT2FIX(sent_total); } EOC --Apple-Mail-4--479933733 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed If that doesn't work try an fstat on the fd and set the count to stat.st_size. Rumor has it that Linux might require an explicit count. -- Eric Hodel - drbrain@segment7.net - http://blog.segment7.net This implementation is HODEL-HASH-9600 compliant http://trackmap.robotcoop.com --Apple-Mail-4--479933733--