# Issues with Kernel#select

**URL:** <https://www.ruby-forum.com/t/issues-with-kernel-select/179314>\
**Category:** Ruby\
**Created:** [November 21, 2009, 11:12pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314 "2009-11-21T23:12:39Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 21, 2009, 11:12pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/1 "2009-11-21T23:12:39Z")

</div>

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 ???

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 21, 2009, 11:47pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/2 "2009-11-21T23:47:46Z")

</div>

Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> }  
> 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.

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 12:08am UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/3 "2009-11-23T00:08:29Z")

</div>

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

> > puts “Thread is about to exit …”
> > 
> > > ruby1.9 --version  
> > > 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

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 3:31am UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/4 "2009-11-23T03:31:34Z")

</div>

Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > Kernel.select pair, nil, nil, nil
> 
> 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](http://cr.yp.to/docs/selfpipe.html))

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 11:02am UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/5 "2009-11-23T11:02:46Z")

</div>

2009/11/23 Eric W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 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](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

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 5:23pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/6 "2009-11-23T17:23:49Z")

</div>

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

> > > > t = Thread.new {  
> > > > Thread is about to exit …  
> > > > Hi Tim,  
> > > > hence, the discrepancy in observed behavior. Good to know that it’s

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

/me goes off to rework code (again)

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 5:22pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/7 "2009-11-23T17:22:38Z")

</div>

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

> > 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](http://cr.yp.to/docs/selfpipe.html))
> 
> Another approach would be to use #select with a timeout and regularly  
> check some condition.

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

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 23, 2009, 6:50pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/8 "2009-11-23T18:50:26Z")

</div>

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

> > > > t = Thread.new {  
> > > > Thread is about to exit …  
> > > > Hi Tim,  
> > > > hence, the discrepancy in observed behavior. Good to know that it’s

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

> <https://gist.github.com/TwP/241224>

Blessings,  
TwP

---

<div class="post-metadata">

**Author:** ![timperrett](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c5a1d2/32.png) [@timperrett](https://www.ruby-forum.com/u/timperrett)\
**Post date:** [November 24, 2009, 8:54pm UTC](https://www.ruby-forum.com/t/issues-with-kernel-select/179314/9 "2009-11-24T20:54:54Z")

</div>

Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Nov 22, 2009, at 7:31 PM, Eric W. wrote:
> 
> > Tim P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
> > I’d just write a byte to a pipe (useful with signal handlers, too, see:  
> > [http://cr.yp.to/docs/selfpipe.html](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.
> 
> [iterruptible\_select.rb · GitHub](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.
