# Thread safety: Serializing access to ruby interpreter- again

**URL:** <https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120>\
**Category:** ruby-talk\
**Created:** [18 September 2003 00:32 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120 "2003-09-18T00:32:21Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Thomas\_Sondergaard](https://avatars.discourse-cdn.com/v4/letter/t/ecae2f/32.png) [@Thomas\_Sondergaard](https://rubytalk.org/u/Thomas_Sondergaard)\
**Post date:** [18 September 2003 00:32 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/1 "2003-09-18T00:32:21Z")

</div>

I recently asked about this and got answers, but here I go again:

How can I efficiently serialize access to the ruby interpreter. I have to  
make sure all access to the ruby interpreter happens on a particular thread  
(not a ruby thread, mind you), so when a different thread attempts to access  
the ruby interpreter I need it to have it post the job to a queue and then  
wait for a ruby worker thread on the ruby-thread (:-)) to execute whatever  
it needs done. Btw, in this mail I use the term ruby-thread, with a dash in  
the middle, as a reference to the heavy-weight thread in which the ruby  
interpreter executes.

The thing is that if I have a ruby thread on the ruby-thread block on a  
heavyweight thread lock the entire ruby-thread is blocked. This is  
demonstrated by this bit below (which requires my dotnet module to work). It  
simply starts a thread that writes to the console continuously and then the  
main thread waits for a signal on anObject. However that wait() call blocks  
the entire ruby-thread not just the “green” ruby main thread, so I never get  
to see a steady stream of hello worlds, and that is what ruins my day.

require ‘dotnet’

t = Thread.new { while true; sleep 0.1; puts “hello world”; end }

anObject = System::EventArgs.new

System::Threading::Monitor.enter(anObject)  
System::Threading::Monitor.wait(anObject) # This blocks the entire  
ruby-thread  
System::Threading::Monitor.exit(anObject)

t.join

So if I am not allowed to touch the ruby interpreter from other threads than  
the ruby-thread how can I wake up a sleeping worker thread when there is  
something for it to do?

Is there a heavyweight-thread-safe way to wake up a ruby thread? Shouldn’t  
there be?

- Thomas

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [18 September 2003 02:20 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/2 "2003-09-18T02:20:29Z")

</div>

Hi,

> So if I am not allowed to touch the ruby interpreter from other threads than  
> the ruby-thread how can I wake up a sleeping worker thread when there is  
> something for it to do?

Using a pipe (or any IO) as the trigger which wakes Monitor up.

> Is there a heavyweight-thread-safe way to wake up a ruby thread? Shouldn’t  
> there be?

Agree, but wait until 1.9 or perhaps 2.0.

> **···**
>
> At Thu, 18 Sep 2003 09:32:21 +0900, Thomas Sondergaard wrote:
> 
> –  
> Nobu Nakada

---

<div class="post-metadata">

**Author:** ![Thomas\_Sondergaard](https://avatars.discourse-cdn.com/v4/letter/t/ecae2f/32.png) [@Thomas\_Sondergaard](https://rubytalk.org/u/Thomas_Sondergaard)\
**Post date:** [19 September 2003 08:37 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/3 "2003-09-19T08:37:09Z")

</div>

Hi Nobu,

> Using a pipe (or any IO) as the trigger which wakes Monitor up.

That doesn’t work. Blocking on a pipe (or any IO) in Windows blocks the  
entire ruby process. This sample will just block and get no where in Windows  
after writing “hello from main” once, while in Linux it happily prints  
“hello from main” once a second.

readPipe, writePipe = IO.pipe

t = Thread.new { while true; sleep 1; puts “got #{readPipe.readline}”; end }

while true  
sleep 1  
puts “hello from main”  
end

t.join

Out of curiousity, why does this happen on Windows? Is it not fixable?

Tom

---

<div class="post-metadata">

**Author:** ![Nobuyoshi\_Nakada](https://avatars.discourse-cdn.com/v4/letter/n/edb3f5/32.png) [@Nobuyoshi\_Nakada](https://rubytalk.org/u/Nobuyoshi_Nakada)\
**Post date:** [24 September 2003 05:58 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/4 "2003-09-24T05:58:16Z")

</div>

Hi,

> > Using a pipe (or any IO) as the trigger which wakes Monitor up.
> 
> That doesn’t work. Blocking on a pipe (or any IO) in Windows blocks the  
> entire ruby process. This sample will just block and get no where in Windows  
> after writing “hello from main” once, while in Linux it happily prints  
> “hello from main” once a second.

Socket might work.

> Out of curiousity, why does this happen on Windows? Is it not fixable?

Because winsock’s select() supports only socket handles.

> **···**
>
> At Fri, 19 Sep 2003 17:37:09 +0900, Thomas Sondergaard wrote:
> 
> –  
> Nobu Nakada

---

<div class="post-metadata">

**Author:** ![Thomas\_Sondergaard](https://avatars.discourse-cdn.com/v4/letter/t/ecae2f/32.png) [@Thomas\_Sondergaard](https://rubytalk.org/u/Thomas_Sondergaard)\
**Post date:** [24 September 2003 09:38 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/5 "2003-09-24T09:38:28Z")

</div>

> Socket might work.

If you say so, I’ll give it a try.

> > Out of curiousity, why does this happen on Windows? Is it not fixable?
> 
> Because winsock’s select() supports only socket handles.

Is all ruby IO implemented in terms of select to avoid blocking the process?  
Why doesn’t select block the process, btw?

Thomas

---

<div class="post-metadata">

**Author:** ![Simon\_Kitching](https://avatars.discourse-cdn.com/v4/letter/s/f04885/32.png) [@Simon\_Kitching](https://rubytalk.org/u/Simon_Kitching)\
**Post date:** [24 September 2003 10:06 UTC](https://rubytalk.org/t/thread-safety-serializing-access-to-ruby-interpreter-again/8120/6 "2003-09-24T10:06:55Z")

</div>

Well, I’m a newbie to Ruby, but unfortunately old enough to remember  
writing C code before real threads existed.

I’m guessing Ruby threads work in the old “cooperative” manner, as  
follows:

What you would do is replace blocking calls to read operations with  
calls to functions implemented like this:

read\_from\_socket:

for(;😉 {  
check for data available  
if data is available  
read data and return it  
else  
schedule some other thread to run // aka “yield”  
}

The check for data is done with a NON-BLOCKING select call, ie one that  
returns immediately even if no data is currently available. In that  
case, the current “thread” stops running and some other “thread” gets  
the CPU. Eventually the current “thread” is rescheduled, goes back to  
the top of the loop, and checks for data again.

It was always a pain to code this way, because you had to call these  
“yielding” versions of standard library calls rather than the real ones,  
for every library function that might block.

However given that languages like Ruby always have “glue” code for  
calling native operations like read & write, it works quite tidily for  
them.

The disadvantage, of course, is that because all threading is  
implemented within a single real OS thread, the app can’t take advantage  
of systems which really have multiple CPUs. And thread “pre-emption” is  
a bit flaky.

I am guessing that Windows doesn’t provide a way to check a socket for  
the presence of data without blocking, meaning that this just can’t be  
implemented.

Cheers,

Simon

> **···**
>
> On Wed, 2003-09-24 at 21:38, Thomas Sondergaard wrote:
> 
> > > Socket might work.
> > 
> > If you say so, I’ll give it a try.
> > 
> > > > Out of curiousity, why does this happen on Windows? Is it not fixable?
> > > 
> > > Because winsock’s select() supports only socket handles.
> > 
> > Is all ruby IO implemented in terms of select to avoid blocking the process?  
> > Why doesn’t select block the process, btw?
> > 
> > Thomas
