From: Jakub Travnik Date: 2001-11-25T02:38:23+09:00 Subject: [ruby-talk:26349] Re: BUG in select More investigations: If I change getc.to_s to sysread(1) in posted source, it works ok. I have investigated what is going on using strace and gdb: Problem is AFAIK in combination of select+threads+buffered stream. (I have changed thread to do sleep 1000 to avoid big strace logs) My strace log: (my comments are orefixed with ####) write(1, "select: [[#, #, #], nil, nil, nil] ) = 64 gettimeofday({1006622392, 833171}, NULL) = 0 #### ruby select will wait: select(5, [0 3], [], [], {999, 998085}a #### I have entered 'a' and enter ) = 1 (in [0], left {988, 110000}) write(1, "select returned: [[#], [], []] ) = 46 #### return is correct: f1 write(1, "f1 will read\n", 13f1 will read ) = 13 gettimeofday({1006622404, 730466}, NULL) = 0 select(1, [0], [], [], {988, 100790}) = 1 (in [0], left {988, 110000}) fstat64(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40027000 ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0 #### now actual read (getc version) read(0, "a\n", 1024) = 2 #### two characters were read, other one is buffered write(1, "f1: 97\n", 7f1: 97 ) = 7 --- SIGVTALRM (Virtual timer expired) --- sigreturn() = ? (mask now []) gettimeofday({1006622404, 733123}, NULL) = 0 select(0, [], [], [], {0, 0}) = 0 (Timeout) #### What is this above? The select call above is useless! #### internal ruby select returned due to buffered character, but returned both f1 and f2!: write(1, "select: [[#, #, #], nil, nil, nil] ) = 64 gettimeofday({1006622404, 733855}, NULL) = 0 gettimeofday({1006622404, 733965}, NULL) = 0 gettimeofday({1006622404, 734061}, NULL) = 0 select(5, [0 3], [], [], {0, 0}) = 0 (Timeout) write(1, "select returned: [[#, #], [], []] ) = 66 write(1, "f1 will read\n", 13f1 will read ) = 13 write(1, "f1: 10\n", 7f1: 10 ) = 7 write(1, "f2 will read\n", 13f2 will read ) = 13 gettimeofday({1006622404, 735405}, NULL) = 0 select(4, [3], [], [], {988, 95851} #### deadlock no data on f2 ready Jakub Travnik wrote: > Hello, > > I found a bug in ruby select method. > Bug is easily repeatable on: > Linux 2.4.3 with: > ruby 1.6.5 stable > ruby stable-snapshot 2001-11-23 > > Description: > Select call with first paramter filled with IO objects should > return IO objects that will not block for next read. It does not > work when there is an another thread. Following code demonstrate > this: > --8<--------------- > require 'thread' > > f1=$stdin # choose any devices that you can read interactively > f2=File.open('/dev/tty8') > > puts "f1: #{f1}" > puts "f2: #{f2}" > > =begin > # uncomment this to see bug > Thread.new{ > loop{ } > } > =end > > loop{ > puts "select: #{[[f1,f2],nil,nil,nil].inspect}" > res=select([f1,f2],nil,nil,nil) > puts "select returned: #{res.inspect}" > if res > res=res[0] > if res.include?(f1) > puts 'f1 will read' > puts 'f1: '+f1.getc.to_s > end > if res.include?(f2) > puts 'f2 will read' > puts 'f2: '+f2.getc.to_s > end > end > } > --8<--------------- > > I have used free allocated consoles /dev/tty8. > Make sure you have no X11 running there! > You can allocate virtual consoles with chvt command. > However it is not significant for this bug, f1 and f2 can be > TCPSocket, UNIXSocket too (like in configuration where bug > appeared first). > Run this, try that you can type something on f1 and f2 > (on consoles enter is required to flush line). > > You should see, that select is returning one IO object at time > (as you feed f1 and f2 with text). > > Now, the bug. > Uncomment thread and run this again. Select returns both f1 > and f2 even when there are no ready data in one of them. > > Thread may be running or blocked in blocking read > (of another IO object) - it does not matter. > > > Jakub Travnik > jabber://jtra@jabber.com > ICQ: 6770334 (deprecated) >