issues with Kernel#select

Discussion in 'Ruby' started by Tim Pease, Nov 21, 2009.

  1. Tim Pease

    Tim Pease Guest

    Waking up a thread that is waiting in Kernel#select does not appear to =
    work in ruby 1.9 Can someone please confirm that this is the case. Is =
    this the intended behavior, or is this a bug?


    > cat a.rb

    require 'socket'

    pair =3D Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    t =3D Thread.new {
    Kernel.select pair, nil, nil, nil
    puts "Thread is about to exit ..."
    }
    t.wakeup
    t.join

    > ruby --version

    ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]

    > ruby a.rb

    Thread is about to exit ...

    > ruby1.9 --version

    ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]

    > ruby1.9 a.rb #=3D> hangs forever!!!!




    Any thoughts out there ???

    Blessings,
    TwP=
    Tim Pease, Nov 21, 2009
    #1
    1. Advertising

  2. Tim Pease

    Eric Wong Guest

    Tim Pease <> wrote:
    > Waking up a thread that is waiting in Kernel#select does not appear to work in ruby 1.9 Can someone please confirm that this is the case. Is this the intended behavior, or is this a bug?
    >
    >
    > > cat a.rb

    > require 'socket'
    >
    > pair = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    > t = Thread.new {
    > Kernel.select pair, nil, nil, nil
    > puts "Thread is about to exit ..."
    > }
    > t.wakeup
    > t.join
    >
    > > ruby --version

    > ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
    >
    > > ruby a.rb

    > Thread is about to exit ...
    >
    > > ruby1.9 --version

    > ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
    >
    > > ruby1.9 a.rb #=> hangs forever!!!!

    >
    >
    >
    > Any thoughts out there ???


    Hi Tim,

    1.9 is actually doing what I expect it to do, that is waiting
    indefinitely because the timeout argument for select is nil. I might
    consider the 1.8.7 behavior a bug, but then again the underlying
    select(2) syscall is allowed to have spurious wakeups. So even without
    a timeout argument, select may always return even when nothing is
    readable.

    --
    Eric Wong
    Eric Wong, Nov 21, 2009
    #2
    1. Advertising

  3. Tim Pease

    Tim Pease Guest

    On Nov 21, 2009, at 3:43 PM, Eric Wong wrote:

    > Tim Pease <> wrote:
    >> Waking up a thread that is waiting in Kernel#select does not appear =

    to work in ruby 1.9 Can someone please confirm that this is the case. =
    Is this the intended behavior, or is this a bug?
    >>=20
    >>=20
    >>> cat a.rb

    >> require 'socket'
    >>=20
    >> pair =3D Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    >> t =3D Thread.new {
    >> Kernel.select pair, nil, nil, nil
    >> puts "Thread is about to exit ..."
    >> }
    >> t.wakeup
    >> t.join
    >>=20
    >>> ruby --version

    >> ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
    >>=20
    >>> ruby a.rb

    >> Thread is about to exit ...
    >>=20
    >>> ruby1.9 --version

    >> ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
    >>=20
    >>> ruby1.9 a.rb #=3D> hangs forever!!!!

    >>=20
    >>=20
    >>=20
    >> Any thoughts out there ???

    >=20
    > Hi Tim,
    >=20
    > 1.9 is actually doing what I expect it to do, that is waiting
    > indefinitely because the timeout argument for select is nil. I might
    > consider the 1.8.7 behavior a bug, but then again the underlying
    > select(2) syscall is allowed to have spurious wakeups. So even =

    without
    > a timeout argument, select may always return even when nothing is
    > readable.


    Thanks for the answer. My suspicion is that the Ruby 1.8 green threads =
    can be woken up, but the Ruby 1.9 system threads "do the right thing"; =
    hence, the discrepancy in observed behavior. Good to know that it's not =
    a bug in 1.9.

    /me goes off to rework code

    Blessings,
    TwP=
    Tim Pease, Nov 22, 2009
    #3
  4. Tim Pease

    Eric Wong Guest

    Tim Pease <> wrote:
    > On Nov 21, 2009, at 3:43 PM, Eric Wong wrote:
    > > Tim Pease <> wrote:
    > >> Waking up a thread that is waiting in Kernel#select does not appear to work in ruby 1.9 Can someone please confirm that this is the case. Is this the intended behavior, or is this a bug?
    > >>
    > >>
    > >>> cat a.rb
    > >> require 'socket'
    > >>
    > >> pair = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    > >> t = Thread.new {
    > >> Kernel.select pair, nil, nil, nil
    > >> puts "Thread is about to exit ..."
    > >> }
    > >> t.wakeup
    > >> t.join
    > >>
    > >>> ruby --version
    > >> ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
    > >>
    > >>> ruby a.rb
    > >> Thread is about to exit ...
    > >>
    > >>> ruby1.9 --version
    > >> ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
    > >>
    > >>> ruby1.9 a.rb #=> hangs forever!!!!
    > >>
    > >>
    > >>
    > >> Any thoughts out there ???

    > >
    > > Hi Tim,
    > >
    > > 1.9 is actually doing what I expect it to do, that is waiting
    > > indefinitely because the timeout argument for select is nil. I might
    > > consider the 1.8.7 behavior a bug, but then again the underlying
    > > select(2) syscall is allowed to have spurious wakeups. So even without
    > > a timeout argument, select may always return even when nothing is
    > > readable.

    >
    > Thanks for the answer. My suspicion is that the Ruby 1.8 green threads
    > can be woken up, but the Ruby 1.9 system threads "do the right thing";
    > hence, the discrepancy in observed behavior. Good to know that it's
    > not a bug in 1.9.
    >
    > /me goes off to rework code


    Yeah, I expect thread.wakeup to only work on thread-aware things like
    sleeping on a condition variable or Thread.sleep. 1.8 wraps select()
    and uses that as the basis of its green thread implementation, so its
    harder to get around spurious wakeups. For reliably waking up IO#select
    I'd just write a byte to a pipe (useful with signal handlers, too, see:
    http://cr.yp.to/docs/selfpipe.html)

    --
    Eric Wong
    Eric Wong, Nov 23, 2009
    #4
  5. 2009/11/23 Eric Wong <>:
    > Tim Pease <> wrote:


    >> Thanks for the answer. My suspicion is that the Ruby 1.8 green threads
    >> can be woken up, but the Ruby 1.9 system threads "do the right thing";
    >> hence, the discrepancy in observed behavior. Good to know that it's
    >> not a bug in 1.9.
    >>
    >> /me goes off to rework code

    >
    > Yeah, I expect thread.wakeup to only work on thread-aware things like
    > sleeping on a condition variable or Thread.sleep. =A01.8 wraps select()
    > and uses that as the basis of its green thread implementation, so its
    > harder to get around spurious wakeups. =A0For reliably waking up IO#selec=

    t
    > I'd just write a byte to a pipe (useful with signal handlers, too, see:
    > http://cr.yp.to/docs/selfpipe.html)


    Another approach would be to use #select with a timeout and regularly
    check some condition.

    Kind regards

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Nov 23, 2009
    #5
  6. Tim Pease

    Tim Pease Guest

    On Nov 23, 2009, at 3:02 AM, Robert Klemme wrote:

    > 2009/11/23 Eric Wong <>:
    >> Tim Pease <> wrote:

    >=20
    >>> Thanks for the answer. My suspicion is that the Ruby 1.8 green =

    threads
    >>> can be woken up, but the Ruby 1.9 system threads "do the right =

    thing";
    >>> hence, the discrepancy in observed behavior. Good to know that it's
    >>> not a bug in 1.9.
    >>>=20
    >>> /me goes off to rework code

    >>=20
    >> Yeah, I expect thread.wakeup to only work on thread-aware things like
    >> sleeping on a condition variable or Thread.sleep. 1.8 wraps select()
    >> and uses that as the basis of its green thread implementation, so its
    >> harder to get around spurious wakeups. For reliably waking up =

    IO#select
    >> I'd just write a byte to a pipe (useful with signal handlers, too, =

    see:
    >> http://cr.yp.to/docs/selfpipe.html)

    >=20
    > Another approach would be to use #select with a timeout and regularly
    > check some condition.
    >=20


    Are you done yet? Are you done yet? Are you done yet? Are you done yet?

    I thought about that, but it's a little more code than I want to write. =
    And I'd like my programs to *not* act like my 3 year old when he's tired =
    ;) Closing the socket is my solution. This is shutdown code ... just =
    need my thread back so I can do some cleanup.

    Thanks for the input.

    Blessings,
    TwP=
    Tim Pease, Nov 23, 2009
    #6
  7. Tim Pease

    Tim Pease Guest

    On Nov 22, 2009, at 7:31 PM, Eric Wong wrote:

    > Tim Pease <> wrote:
    >> On Nov 21, 2009, at 3:43 PM, Eric Wong wrote:
    >>> Tim Pease <> wrote:
    >>>> Waking up a thread that is waiting in Kernel#select does not appear =

    to work in ruby 1.9 Can someone please confirm that this is the case. =
    Is this the intended behavior, or is this a bug?
    >>>>=20
    >>>>=20
    >>>>> cat a.rb
    >>>> require 'socket'
    >>>>=20
    >>>> pair =3D Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    >>>> t =3D Thread.new {
    >>>> Kernel.select pair, nil, nil, nil
    >>>> puts "Thread is about to exit ..."
    >>>> }
    >>>> t.wakeup
    >>>> t.join
    >>>>=20
    >>>>> ruby --version
    >>>> ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
    >>>>=20
    >>>>> ruby a.rb
    >>>> Thread is about to exit ...
    >>>>=20
    >>>>> ruby1.9 --version
    >>>> ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
    >>>>=20
    >>>>> ruby1.9 a.rb #=3D> hangs forever!!!!
    >>>>=20
    >>>>=20
    >>>>=20
    >>>> Any thoughts out there ???
    >>>=20
    >>> Hi Tim,
    >>>=20
    >>> 1.9 is actually doing what I expect it to do, that is waiting
    >>> indefinitely because the timeout argument for select is nil. I =

    might
    >>> consider the 1.8.7 behavior a bug, but then again the underlying
    >>> select(2) syscall is allowed to have spurious wakeups. So even =

    without
    >>> a timeout argument, select may always return even when nothing is
    >>> readable.

    >>=20
    >> Thanks for the answer. My suspicion is that the Ruby 1.8 green =

    threads
    >> can be woken up, but the Ruby 1.9 system threads "do the right =

    thing";
    >> hence, the discrepancy in observed behavior. Good to know that it's
    >> not a bug in 1.9.
    >>=20
    >> /me goes off to rework code

    >=20
    > Yeah, I expect thread.wakeup to only work on thread-aware things like
    > sleeping on a condition variable or Thread.sleep. 1.8 wraps select()
    > and uses that as the basis of its green thread implementation, so its
    > harder to get around spurious wakeups. For reliably waking up =

    IO#select
    > I'd just write a byte to a pipe (useful with signal handlers, too, =

    see:
    > http://cr.yp.to/docs/selfpipe.html)
    >=20


    Oooooohhhhh ... rainbows and unicorns, indeed!! Great link.

    /me goes off to rework code (again)

    Blessings,
    TwP=
    Tim Pease, Nov 23, 2009
    #7
  8. Tim Pease

    Tim Pease Guest

    On Nov 22, 2009, at 7:31 PM, Eric Wong wrote:

    > Tim Pease <> wrote:
    >> On Nov 21, 2009, at 3:43 PM, Eric Wong wrote:
    >>> Tim Pease <> wrote:
    >>>> Waking up a thread that is waiting in Kernel#select does not appear =

    to work in ruby 1.9 Can someone please confirm that this is the case. =
    Is this the intended behavior, or is this a bug?
    >>>>=20
    >>>>=20
    >>>>> cat a.rb
    >>>> require 'socket'
    >>>>=20
    >>>> pair =3D Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
    >>>> t =3D Thread.new {
    >>>> Kernel.select pair, nil, nil, nil
    >>>> puts "Thread is about to exit ..."
    >>>> }
    >>>> t.wakeup
    >>>> t.join
    >>>>=20
    >>>>> ruby --version
    >>>> ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10]
    >>>>=20
    >>>>> ruby a.rb
    >>>> Thread is about to exit ...
    >>>>=20
    >>>>> ruby1.9 --version
    >>>> ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]
    >>>>=20
    >>>>> ruby1.9 a.rb #=3D> hangs forever!!!!
    >>>>=20
    >>>>=20
    >>>>=20
    >>>> Any thoughts out there ???
    >>>=20
    >>> Hi Tim,
    >>>=20
    >>> 1.9 is actually doing what I expect it to do, that is waiting
    >>> indefinitely because the timeout argument for select is nil. I =

    might
    >>> consider the 1.8.7 behavior a bug, but then again the underlying
    >>> select(2) syscall is allowed to have spurious wakeups. So even =

    without
    >>> a timeout argument, select may always return even when nothing is
    >>> readable.

    >>=20
    >> Thanks for the answer. My suspicion is that the Ruby 1.8 green =

    threads
    >> can be woken up, but the Ruby 1.9 system threads "do the right =

    thing";
    >> hence, the discrepancy in observed behavior. Good to know that it's
    >> not a bug in 1.9.
    >>=20
    >> /me goes off to rework code

    >=20
    > Yeah, I expect thread.wakeup to only work on thread-aware things like
    > sleeping on a condition variable or Thread.sleep. 1.8 wraps select()
    > and uses that as the basis of its green thread implementation, so its
    > harder to get around spurious wakeups. For reliably waking up =

    IO#select
    > I'd just write a byte to a pipe (useful with signal handlers, too, =

    see:
    > http://cr.yp.to/docs/selfpipe.html)
    >=20


    Based on the self-pipe page, here is the solution I came up with. =
    Please, anyone, give comments and suggestions.

    http://gist.github.com/241224

    Blessings,
    TwP
    Tim Pease, Nov 23, 2009
    #8
  9. Tim Pease

    Eric Wong Guest

    Tim Pease <> wrote:
    > On Nov 22, 2009, at 7:31 PM, Eric Wong wrote:
    > > Tim Pease <> wrote:
    > > I'd just write a byte to a pipe (useful with signal handlers, too, see:
    > > http://cr.yp.to/docs/selfpipe.html)
    > >

    >
    > Based on the self-pipe page, here is the solution I came up with.
    > Please, anyone, give comments and suggestions.
    >
    > http://gist.github.com/241224


    Hi Tim,

    I think a length argument is is required for read_nonblock. And
    you should probably only be reading from the receiver *after* the
    select.

    Also, the creation/check of Thread#[:select_signal_pipe] is
    potentially racy. I would probably create it in the parent
    like this:

    pipe = IO.pipe
    thr = Thread.new(pipe) do |pipe|
    Thread.current[:select_signal_pipe] = pipe
    pipe.last.syswrite('.') # wakeup parent once we know the parent can use it
    # ...
    end
    pipe.first.readpartial 1 # blocks until it reads '.'
    # after the readpartial, we know the following is set:
    assert(thr[:select_signal_pipe] == pipe)
    # ...

    Unlike the self-pipe example, the basic rule of thumb to avoid driving
    oneself nuts is that one set of threads/processes only does reads, and
    another set only does writes. Reading and writing to one pipe from the
    same thread/process anywhere outside of signal handlers gets really
    confusing, really quickly :> And even with the self-pipe signal
    handlers, all communication is one-way within any given control block.

    I'd also be very defensive about spurious select() wakeups (and
    Errno::EINTR, too, just in case). Pretty much any syscall that sleeps
    like select() including (but not limited to) pthread_cond_wait, poll,
    epoll_wait are all *potentially* susceptible to spurious wakeups, so you
    could be exiting a thread when you don't intend to.

    --
    Eric Wong
    Eric Wong, Nov 24, 2009
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. yogesh
    Replies:
    3
    Views:
    570
    Kenny McCormack
    Feb 12, 2006
  2. C Erler
    Replies:
    3
    Views:
    123
    Ara.T.Howard
    Jun 28, 2005
  3. Jon Smirl

    kernel#select and threads

    Jon Smirl, Dec 23, 2005, in forum: Ruby
    Replies:
    3
    Views:
    110
    Bill Kelly
    Dec 24, 2005
  4. Replies:
    3
    Views:
    155
  5. Lars Gierth
    Replies:
    6
    Views:
    207
    David Masover
    Mar 20, 2010
Loading...

Share This Page