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

Race condition in Nokogiri::CSS::Parser #1935

Closed
ioquatix opened this issue Oct 23, 2019 · 5 comments · Fixed by #1995
Closed

Race condition in Nokogiri::CSS::Parser #1935

ioquatix opened this issue Oct 23, 2019 · 5 comments · Fixed by #1995
Milestone

Comments

@ioquatix
Copy link

#!/usr/bin/env ruby

require 'nokogiri'

parser = Nokogiri::CSS::Parser.new

puts Nokogiri::CSS::Parser.cache_on?

threads = []

threads << Thread.new do
	Nokogiri::CSS::Parser.without_cache do
		sleep 1
	end
end

threads << Thread.new do
	sleep 0.1
	
	Nokogiri::CSS::Parser.without_cache do
		sleep 2
	end
end

threads.each(&:join)

puts Nokogiri::CSS::Parser.cache_on?

# Prints false, but should be true.
@flavorjones
Copy link
Member

Thanks for reporting, I'll take a look as soon as I can.

@ioquatix
Copy link
Author

The reason why it happens is because there is no locking around @cache_on which is shared global state:

def without_cache &block
tmp = @cache_on
@cache_on = false
block.call
@cache_on = tmp
end

@ioquatix
Copy link
Author

ioquatix commented Nov 1, 2019

The solution is to use Thread.current[:nokogiri_cache_on] and assign to it directly rather than trying to read/write shared mutable state.

@flavorjones
Copy link
Member

@ioquatix Can I ask how you found this bug? The #without_cache method was added in 8b9daef, and is only used in the Slop node decorator ... are you using #without_cache for something? I'm just curious.

You're right, of course, and we'll fix it.

flavorjones added a commit that referenced this issue Feb 15, 2020
flavorjones added a commit that referenced this issue Feb 15, 2020
fixes #1935

also:
- remove internal method `Nokogiri::CSS::Parser.cache_on=` in favor of`.set_cache`
- add more test coverage to the CSS cache
@flavorjones flavorjones added this to the v1.11.0 milestone Feb 15, 2020
@ioquatix
Copy link
Author

I found it by manual analysis supported by some tools like grep and custom scripts to narrow down on potential issues.

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

Successfully merging a pull request may close this issue.

2 participants