Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IO.puts is not thread safe #3182

Closed
samwgoldman opened this issue Jul 24, 2015 · 2 comments
Closed

IO.puts is not thread safe #3182

samwgoldman opened this issue Jul 24, 2015 · 2 comments
Milestone

Comments

@samwgoldman
Copy link

I have some logging code that looks like this:

def log(line)
  io.puts(line)
  io.fsync
end

This code is called from multiple threads.

In production, I've noticed lines that there are lines that look like this: "#{line1}#{line2}\n\n".

I looked into it, and it looks like puts might have a race condition between writing the line and writing the subsequent newline. See

write(context, maybeIO, separator.getByteList());
.

Some repro code:

require 'thread'
8.times.map do
  Thread.new do
    1000.times do
      $stdout.puts "line"
      $stdout.fsync
    end
  end
end.map(&:join)

To test:

ruby puts.rb | grep lineline

/cc @cheald

@Freaky
Copy link
Contributor

Freaky commented Jul 24, 2015

MRI does exactly the same thing: https://github.com/ruby/ruby/blob/trunk/io.c#L7102

You've always had to do io.write "line\n" to avoid it.

@cheald
Copy link
Contributor

cheald commented Jul 24, 2015

As Freaky points out, MRI does indeed exhibit this interleaving behavior.

That said, I would argue the behavior is surprising and probably should be fixed in MRI, too!

@kares kares added this to the Won't Fix milestone Jun 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants