[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

In need of Win32 fcntl (non-blocking

Ivo Palli

1/25/2005 3:01:00 PM

Hi there,

I am making a multi-user, telnet based, bbs. At work I use Linux Ruby,
at home a Win32 port. (http://rubyinstaller.rubyforge.org/wi...)

Now a multi-user server can be done in threads, but since I want to keep
it simple and avoid dead-locks and starvation problems, I decided not to
use threads. (I also read that threads can block the whole program if
they get stuck in system calls. That's not something I want.)

Instead I want to use a select, which is thankfully support in Ruby.
However a read to a socket which has data open always seems to block,
unless I specifically read what is available. Since I cannot know how
much data is waiting for me, I really need to do a non-blocking read. In
Linux it works, in Windows the fcntl call is not supported. :( As far as
I searched and tried, there is no other way to read data without blocking.

This guy

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby...

seems to have made a fix some time ago. Can I ask why it is not in the
standard distribution? On that note, can somebody point me to a binary
win32 distribution that _does_ have this patch incorporated?

One last thing. I ran the example below on both Linux and Win32.
Normally stdout buffering is done up until a '\n' after which output is
flushed (ANSI C, both on Linux and Win32). This behaviour is seen on the
Linux Ruby port, but not under Win32 where I had to put in
'STDOUT.sync=true'. Can this be considered a bug?

I'm using:
ruby 1.8.2 (2004-12-25) [i386-mswin32]
ruby 1.8.2 (2004-12-25) [i686-linux]



Server example, works on Linux, not on Win32:

# socket example - server side
# usage: ruby svr.rb

require "socket"
require "fcntl"

gs = TCPserver.open(0)
addr = gs.addr
addr.shift
printf("server is on %s\n", addr.join(":"))
socks = [gs]

loop do
nsock = select(socks);
next if nsock == nil
for s in nsock[0]
if s == gs
ns = s.accept
ns.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
socks.push(ns)
print(s, " is accepted\n")
else
if s.eof?
print(s, " is gone\n")
s.close
socks.delete(s)
else
print "[" + s.read + "]\n"
end
end
end
end





6 Answers

Tanaka Akira

1/25/2005 3:28:00 PM

0

In article <41F65F1B.80706@palli.nl>,
Ivo Palli <ivo@palli.nl> writes:

> Instead I want to use a select, which is thankfully support in Ruby.
> However a read to a socket which has data open always seems to block,
> unless I specifically read what is available. Since I cannot know how
> much data is waiting for me, I really need to do a non-blocking read. In
> Linux it works, in Windows the fcntl call is not supported. :( As far as
> I searched and tried, there is no other way to read data without blocking.

sysread might be usable because sysread doesn't block when some data
available. If sysread is usable, you don't need non-blocking read.

require "socket"

gs = TCPserver.open(0)
addr = gs.addr
addr.shift
printf("server is on %s\n", addr.join(":"))
socks = [gs]

loop do
nsock = select(socks);
next if nsock == nil
for s in nsock[0]
if s == gs
ns = s.accept
socks.push(ns)
print(s, " is accepted\n")
else
begin
print "[" + s.sysread(4096) + "]\n"
rescue EOFError
print(s, " is gone\n")
s.close
socks.delete(s)
end
end
end
end
--
Tanaka Akira


Ivo Palli

1/25/2005 5:38:00 PM

0

You are correct, sysread() returns without blocking. However this is a
workaround at best. In the interest of portability over platforms, I
still recommend for fcntl() to be implemented in the Win32 platform.
Afterall Ruby aims to provide a unified platform regardless of OS. Right?

Are there any ways to detect the OS btw? If I'm going to run my script
on multiple platforms, and I need to workaround, how can I do this
automatically?

Regards,

Ivo Palli

Tanaka Akira wrote:
> In article <41F65F1B.80706@palli.nl>,
> Ivo Palli <ivo@palli.nl> writes:
>
>
>>Instead I want to use a select, which is thankfully support in Ruby.
>>However a read to a socket which has data open always seems to block,
>>unless I specifically read what is available. Since I cannot know how
>>much data is waiting for me, I really need to do a non-blocking read. In
>>Linux it works, in Windows the fcntl call is not supported. :( As far as
>>I searched and tried, there is no other way to read data without blocking.
>
>
> sysread might be usable because sysread doesn't block when some data
> available. If sysread is usable, you don't need non-blocking read.
>
> require "socket"
>
> gs = TCPserver.open(0)
> addr = gs.addr
> addr.shift
> printf("server is on %s\n", addr.join(":"))
> socks = [gs]
>
> loop do
> nsock = select(socks);
> next if nsock == nil
> for s in nsock[0]
> if s == gs
> ns = s.accept
> socks.push(ns)
> print(s, " is accepted\n")
> else
> begin
> print "[" + s.sysread(4096) + "]\n"
> rescue EOFError
> print(s, " is gone\n")
> s.close
> socks.delete(s)
> end
> end
> end
> end



djberg96

1/25/2005 7:44:00 PM

0

Ivo Palli wrote:
> Are there any ways to detect the OS btw? If I'm going to run my
script
> on multiple platforms, and I need to workaround, how can I do this
> automatically?
>
> Regards,
>
> Ivo Palli

If you just need to detect Windows vs Unix, you can use
File::ALT_SEPARATOR. It's only true on Win32.

If you want a little more detail, you can use the RUBY_VERSION
constant.

If you want a lot more detail, see sys-uname, available on the RAA.
Regards,

Dan

Csaba Henk

1/26/2005 2:01:00 AM

0

On 2005-01-25, Ivo Palli <ivo@palli.nl> wrote:
> Are there any ways to detect the OS btw?

require 'rbconfig'
Config::CONFIG['target']

Csaba

nobu.nokada

1/30/2005 4:44:00 AM

0

Hi,

At Wed, 26 Jan 2005 00:00:58 +0900,
Ivo Palli wrote in [ruby-talk:128097]:
> This guy
>
> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby...
>
> seems to have made a fix some time ago. Can I ask why it is not in the
> standard distribution? On that note, can somebody point me to a binary
> win32 distribution that _does_ have this patch incorporated?

[ruby-core:3157] has been committed to CVS HEAD instead, but
not backported to 1.8 yet.

--
Nobu Nakada


Joao Pedrosa

1/30/2005 4:50:00 AM

0

Hi,

On Sun, 30 Jan 2005 13:44:06 +0900, nobu.nokada@softhome.net
<nobu.nokada@softhome.net> wrote:
> Hi,
>
> At Wed, 26 Jan 2005 00:00:58 +0900,
> Ivo Palli wrote in [ruby-talk:128097]:
> > This guy
> >
> > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby...
> >
> > seems to have made a fix some time ago. Can I ask why it is not in the
> > standard distribution? On that note, can somebody point me to a binary
> > win32 distribution that _does_ have this patch incorporated?
>
> [ruby-core:3157] has been committed to CVS HEAD instead, but
> not backported to 1.8 yet.

This is good news. I'm going to test this later. Thanks!

Regards,
Joao