0

Is it expected that the current thread will be the same across concurrent requests to "free" passenger?

I've got a bug in that thread local ruby variables are not independent to concurrent requests. I.e., the same thread id shows for both of two concurrent requests (simulated with a sleep to slow things down).

Is this different for Passenger enterprise edition?

Is there a proper way to get a thread local variable that is isolated for the life of a single request in Rails?

UPDATED:

  1. Problem is not specific to Passenger. Problem is there for Thin as well.
  2. Other libraries, such as paper_trail may have this issue: https://github.com/airblade/paper_trail/issues/499
  3. Here's a potential fix: https://github.com/steveklabnik/request_store, along with a detailed description of the issue I'm seeing.
justingordon
  • 12,553
  • 12
  • 72
  • 116
  • No. Even in free passenger, you should not count on the thread being the same accross requests. Free passenger doesn't really have 'concurrent' requests at all. BUT. In general, you should never expect the the current thread to ever be the same from request to request -- but it MAY be for consecutive requests, threads may be re-used. – jrochkind Mar 18 '15 at 21:58
  • I'm not trying to keep a value across requests. I'm trying to keep a value for the entire duration of a request. – justingordon Mar 19 '15 at 04:29

2 Answers2

1

If you want a request-local variable, consider putting it into the Rack request env object. See the answers on this question for a more complete rundown.

Regarding thread locals, that certainly seems like unexpected behavior, but it's entirely possible that Passenger is doing something that doesn't guarantee that a single thread will be owned by a request for its whole lifetime. The Rack::Lock middleware usually solves this by taking a mutex around the whole request, but if you've removed it, you aren't guaranteed to have that synchronization. In general, thread-local variables are a code smell and probably an indicator that you're doing something you shouldn't.

Community
  • 1
  • 1
Chris Heald
  • 61,439
  • 10
  • 123
  • 137
  • Thanks Chris. Please take a look at the update I posted above. – justingordon Mar 18 '15 at 21:04
  • RequestStore seems like it's just using threadlocals which get cleared after each request. I'm not convinced that's going to fix the issue for you. Are you using EventMachine/something else that is going to invoke fibers for concurrency, and what version of Ruby are you running this under? – Chris Heald Mar 18 '15 at 21:08
  • Because a controller request will be handled by a given thread from start to end, the issue I actually had was that the value stuck around after the end of the request. RequestStore solved that perfectly. – justingordon Mar 19 '15 at 06:43
0

Solved:

Thread.current[:something] is not as you'd expect with Thin and Passenger!!

Not sure about Unicorn and Puma.

Add the request_store gem, and follow the instructions to solve this issue.

justingordon
  • 12,553
  • 12
  • 72
  • 116