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

Fix template compilation concurrency issue #6401

Closed
wants to merge 3 commits into from

Conversation

pinetops
Copy link
Contributor

This addresses issue #6400.

I made the change against 3.2.3-rc2, but it also applies almost cleanly against master (just a few whitespace issues) and cleanly against 3.1-stable.

@wycats
Copy link
Member

wycats commented May 20, 2012

The idea behind the original implementation is that templates would only be compiled in development mode (which is always single-threaded) or ahead of time in threadsafe mode.

What actual scenario triggers this problem?

@pinetops
Copy link
Contributor Author

@wycats - I was observing empirically with a clean generated rails app (with threadsafe mode enabled) that the templates aren't compiled ahead of time. They're compiled on demand, and if there are multiple requests for the same url when it is first requested then you can get two threads going through the compile process at the same time. I verified this by instrumenting the code. And verified that the fix, serializes the access and makes sure a particular template gets compiled precisely once.

In practice I've had this happen several times on a production app, where a particular url is permanently damaged, and unable to be used until the next server restart.

I wasn't aware of any functionality that allowed templates to be compiled ahead of time - is there such a thing? If so that would be a satisfactory solution.

# so compilation and any instance variable modification must
# be synchronized
@compile_mutex.synchronize {
return if @compiled
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unecessary line here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind. It is necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, can you please add some extra comments above this line? I think almost everyone first reaction is that the duplicated line is useless. :)

@josevalim
Copy link
Contributor

@wycats this seems correct to me. we don't do ahead of time compilation.



This change avoids obtaining a lock for templates that are already compiled by
using a thread local copy of any templates already used by the thread.

There are a few issues with this however:
- It breaks ActionView::Template::Resolver#clear_cache, as there's no good way of
  clearing all the Thread local copies. Within Rails it's only used in one test
  (which could be implemented another way). So the question is possibly if this is
  intented to be part of the public API and if it can be removed.
- If there's any scenario in which Resolvers can be re-created there is a potential
  memory leak as there's no attempt to clear up the thread local storage
- I don't have any performance data to justify the need to avoid locks
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 this pull request may close these issues.

None yet

3 participants