Threads: Different behavior under Linux and Windows

Discussion in 'Ruby' started by Armin Armbruster, Jul 8, 2008.

  1. Hi,

    I've tried the sample code below on Ubuntu (7.04) as well as on a
    Windows XP machine.
    While under Linux I get the expected result, namely task 1 counting
    away, under XP task 1 stalls until I enter something, then runs one loop
    and stalls again.
    I would have thought that the call to gets in task 2 only blocks task 2,
    but not task 1.
    Can anybody please explain this to me and more importantly show me a
    solution on how to do this so it works under Windows as well?

    Thanks in advance,
    Armin

    require 'thread'

    t1 = Thread.new{
    count = 0
    loop{
    count += 1
    sleep 1
    print "T1: #{count}\n"
    }
    }

    t2 = Thread.new{
    loop{
    a = gets
    print " T2: a = #{a}\n"
    }
    }

    t1.join
    t2.join
    --
    Posted via http://www.ruby-forum.com/.
    Armin Armbruster, Jul 8, 2008
    #1
    1. Advertising

  2. Armin Armbruster

    ara.t.howard Guest

    On Jul 8, 2008, at 8:26 AM, Armin Armbruster wrote:

    > Can anybody please explain this to me and more importantly show me a
    > solution on how to do this so it works under Windows as well?


    it's well known - on windows *all* threads are blocked when the
    process is blocked on IO.

    a @ http://codeforpeople.com/
    --
    we can deny everything, except that we have the possibility of being
    better. simply reflect on that.
    h.h. the 14th dalai lama
    ara.t.howard, Jul 8, 2008
    #2
    1. Advertising

  3. ara.t.howard schrieb:
    > On Jul 8, 2008, at 8:26 AM, Armin Armbruster wrote:
    >
    >> Can anybody please explain this to me and more importantly show me a
    >> solution on how to do this so it works under Windows as well?

    >
    > it's well known - on windows *all* threads are blocked when the
    > process is blocked on IO.


    that sure is not because of windows itself... so is there a page
    explaining why this is so?

    bye Jochen
    Jochen Theodorou, Jul 8, 2008
    #3
  4. Armin Armbruster

    ara.t.howard Guest

    ara.t.howard, Jul 8, 2008
    #4
  5. ara.t.howard wrote:
    > On Jul 8, 2008, at 9:16 AM, Jochen Theodorou wrote:
    >
    >> that sure is not because of windows itself... so is there a page
    >> explaining why this is so?

    >
    >
    > http://groups.google.com/group/ruby...q=thread block windows&qt_g=Search this group
    >
    > also, the pickaxe covers this in the 'threads and processes' chapter
    >
    > a @ http://codeforpeople.com/


    Thanks for your replies Ara.
    I tried to find it in the pickaxe (second edition), Chapter 11, but I
    couldn't find anything mentioned about this particular behavior under
    Windows.
    Also I tried to follow the discussion on google groups but didn't find a
    solution described.

    So now I'm stuck. Here's what I really want to do, maybe someone can
    show me a solution to this?
    I'd like to write a little terminal application.

    1. Open a serial port
    2. Create a sender task that waits for user input on stdin and sends the
    data out the serial port.
    3. Create a receiver task that waits for data coming from the serial
    port and output it on the screen.

    Any suggestions?

    Thanks,
    Armin
    --
    Posted via http://www.ruby-forum.com/.
    Armin Armbruster, Jul 8, 2008
    #5
  6. Armin Armbruster

    ara.t.howard Guest

    On Jul 8, 2008, at 11:59 AM, Armin Armbruster wrote:

    > So now I'm stuck. Here's what I really want to do, maybe someone can
    > show me a solution to this?
    > I'd like to write a little terminal application.
    >
    > 1. Open a serial port
    > 2. Create a sender task that waits for user input on stdin and sends
    > the
    > data out the serial port.
    > 3. Create a receiver task that waits for data coming from the serial
    > port and output it on the screen.
    >
    > Any suggestions?
    >
    > Thanks,
    > Armin


    seems like a class case of using select?

    if select( [stdin, serial], nil, nil, 0.2 )
    ...




    steve shreeve has had some luck using this paradigm:



    require 'socket'

    def socketpair
    if RUBY_PLATFORM.include?("win32")
    listen = TCPServer.new('127.0.0.1', 0)
    client = TCPSocket.new('127.0.0.1', listen.addr[1])
    server = listen.accept and listen.close
    [client, server]
    else
    UNIXSocket.socketpair
    end
    end

    c,s = socketpair

    require 'win32/process'
    info = Process.create(
    'app_name' => 'cmd /c "type d:\four_megs.txt & pause"',
    'startup_info' => {
    'stdin' => c,
    'stdout' => c,
    }
    )
    c.close # needed?


    to get nonblocking (in a thread) io on windows.



    regards.

    a @ http://codeforpeople.com/
    --
    we can deny everything, except that we have the possibility of being
    better. simply reflect on that.
    h.h. the 14th dalai lama
    ara.t.howard, Jul 8, 2008
    #6
  7. Armin Armbruster, Jul 8, 2008
    #7
  8. On Jul 8, 8:46=A0am, "ara.t.howard" <> wrote:
    > On Jul 8, 2008, at 8:26 AM, Armin Armbruster wrote:
    >
    > > Can anybody please explain this to me and more importantly show me a
    > > solution on how to do this so it works under Windows as well?

    >
    > it's well known - on windows *all* threads are blocked when the =A0
    > process is blocked on IO.


    It's actually a bug in MRI. JRuby does not exhibit that behavior, for
    example. Park Heesob posted a patch a short while back that fixes it,
    too. That patch has already been applied to Sapphire.

    Regards,

    Dan
    Daniel Berger, Jul 8, 2008
    #8
  9. Armin Armbruster

    Luis Lavena Guest

    On Jul 8, 5:19 pm, Jochen Theodorou <> wrote:
    > ara.t.howard schrieb:
    >
    > > On Jul 8, 2008, at 8:26 AM, Armin Armbruster wrote:

    >
    > >> Can anybody please explain this to me and more importantly show me a
    > >> solution on how to do this so it works under Windows as well?

    >
    > > it's well known - on windows *all* threads are blocked when the  
    > > process is blocked on IO.

    >
    > that sure is not because of windows itself... so is there a page
    > explaining why this is so?
    >


    No, is not a Windows problem but MRI Ruby Implementation Issue.

    Ruby Threads are actually Green Threads (not real threads) so the
    interpreter need to loop in them to be able to process them. When IO
    is performed in the same thread (since 1.8 is single threaded) it
    blocks and stop the green threads to be processed.

    This is quite old actually, and been discussed several times here and
    ruby-core (search for Io Thread and gets).

    There was some changes introduced after p114 (1.8.6) but they needed
    to be reverted because they introduced some issues on MinGW
    compilation and Drb, which halt the tests (you can also look for that
    in ruby-core)

    At this time there is no solution for it, except to avoid that
    scenario or jump to something like EventMachine to perform that task
    (search for EventMachine Console in this forum).

    HTH,
    --
    Luis Lavena
    Luis Lavena, Jul 9, 2008
    #9
  10. Armin Armbruster

    Luis Lavena Guest

    On Jul 8, 9:00 pm, Daniel Berger <> wrote:
    > On Jul 8, 8:46 am, "ara.t.howard" <> wrote:
    >
    > > On Jul 8, 2008, at 8:26 AM, Armin Armbruster wrote:

    >
    > > > Can anybody please explain this to me and more importantly show me a
    > > > solution on how to do this so it works under Windows as well?

    >
    > > it's well known - on windows *all* threads are blocked when the  
    > > process is blocked on IO.

    >
    > It's actually a bug in MRI. JRuby does not exhibit that behavior, for
    > example. Park Heesob posted a patch a short while back that fixes it,
    > too. That patch has already been applied to Sapphire.
    >


    Hey Dan, can you confirm if that patches make Drb tests stall or pass?
    similar change introduced in 1.8 (but reverted due this) stall at
    least for GCC.

    Maybe we can give another shot at this and merge into 1.8 again.

    Thank you,
    --
    Luis Lavena
    Luis Lavena, Jul 9, 2008
    #10
  11. On Wed, Jul 9, 2008 at 5:07 PM, Luis Lavena <> wrote:
    >
    > Hey Dan, can you confirm if that patches make Drb tests stall or pass?
    > similar change introduced in 1.8 (but reverted due this) stall at
    > least for GCC.
    >
    > Maybe we can give another shot at this and merge into 1.8 again.
    >
    > Thank you,
    > --
    > Luis Lavena
    >
    >


    Also, a recently added spec in Rubyspec is hanging when using threads.
    The code that hangs is in 1.8\library\socket\tcpsocket\shared\new.rb.
    This is the failing example: http://pastie.org/231434

    If you run:

    >mspec 1.8/library/socket/tcpsocket


    You should see it hang.

    The offending code is run once for tcpsocket/new_spec.rb and once for
    tcpsocket/open_spec.rb. If you run either file individually, no
    problems. Do you think this is the same problem?

    I've tested on these version:

    ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]
    ruby 1.8.6 (2008-03-03 patchlevel 114) [i386-mingw32]
    ruby 1.8.6 (2008-07-03 patchlevel 265) [i386-mingw32]

    Thanks,

    Gordon Thiesfeld
    Gordon Thiesfeld, Jul 10, 2008
    #11
  12. On Thu, Jul 10, 2008 at 7:16 AM, Gordon Thiesfeld <> wrote:
    > Also, a recently added spec in Rubyspec is hanging when using threads.


    There was a problem with the spec. Sorry for the noise.

    Gordon
    Gordon Thiesfeld, Jul 10, 2008
    #12
  13. Hi guys,

    this problem has been costing me some nerves now. I've tried various
    things, including EventMachine, with no luck (maybe I did something
    wrong).

    Anyhow, I finally gave up trying a direct approach and tried a
    sub-process/socket approach similar to what Ara suggested.
    Here's something that finally works:

    require 'socket'
    require 'win32/process'

    PORT_NUMBER = 12345

    CHILD_PROC = 'ruby -e "' <<
    'sleep 0.1;' <<
    'csock = TCPSocket.new(\'localhost\',' << PORT_NUMBER.to_s <<
    ');' <<
    'loop{a = gets; csock.print a; exit if a =~ /^exit$/;}'

    p = Process.create:)app_name => CHILD_PROC)
    #create a green thread that counts every second, to prove that the
    parent process is not blocked
    t = Thread.new{c = 0; loop{c+=1; puts c;sleep 1}}

    l = TCPServer.new('localhost', PORT_NUMBER)
    psock = l.accept and l.close
    loop{ a = psock.gets; print "Got: #{a}"; exit if exit if a =~ /^exit$/;}

    (Note: the example isn't very useful, all it's supposed to show is that
    the ticker thread is still running while the loop in the parent thread
    is blocking on the psock.gets).

    I have to admit that I'm not very experienced with either windows
    programming or network programming, so while this works I still have
    some questions.

    1. Both parent and child process run in the same console window. Who
    "owns" stdin, stdout and stderr? Is there a way that the child process
    could own stdin and the parent stdout and stderr?

    2. Luis/Dan - you mentioned that Park Heesob has submitted a patch that
    should actually fix the original problem in MRI, but that there were
    some problems with it and therefore it had been reverted. Does anybody
    know whether the latest patchlevel of 1.8.6 (p115 I think) does have the
    problem fixed? If yes, can I download the patch in binary format (so far
    I've been using the One-click-installer, I have no experience with
    building ruby from source).

    3. How does fxri circumvent this problem? I can start a ticker thread in
    fxri and it's happily ticking away. If I try the same thing in irb in a
    console, the ticker stalls until I type stuff.

    Thanks,
    Armin
    --
    Posted via http://www.ruby-forum.com/.
    Armin Armbruster, Jul 25, 2008
    #13
    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. Jim Davis
    Replies:
    1
    Views:
    406
    John Saunders
    Jun 9, 2004
  2. hshdude
    Replies:
    12
    Views:
    1,055
    Dimitri Maziuk
    Nov 4, 2004
  3. bronby
    Replies:
    1
    Views:
    606
    Andrew Thompson
    Jul 15, 2005
  4. Luke Kenneth Casson Leighton
    Replies:
    0
    Views:
    366
    Luke Kenneth Casson Leighton
    Jan 15, 2009
  5. db
    Replies:
    6
    Views:
    94
Loading...

Share This Page