toland / patron

Ruby HTTP client based on libcurl
http://toland.github.com/patron/
MIT License
541 stars 73 forks source link

Enable support for Ruby 1.9 "thread blocking region" #47

Closed TwP closed 12 years ago

TwP commented 12 years ago

Two issues were preventing proper operation of the Ruby thread blocking region code.

As you mentioned before, using a ruby string buffer to collect the header and body data from the curl request was unsafe. Calling back into the Ruby interpreter without first reacquiring the global interpreter lock is very dangerous. So I took your advice and created a memory buffer structure to accumulate the curl responses instead of relaying on the rb_str_buf methods.

When curl is used within a multi-threaded environment, it uses signals for handling some of the timeout code. The Ruby interpreter will handle these signals by default. This results in a situation where the signal fired from curl (which has released the GIL) is handled by Ruby code - again triggering this unsafe situation where the GIL has not been reacquired. I have set the CURLOPT_NOSIGNAL flag on the session. This appears to resolve the issue, and timeouts still function properly.

TwP commented 12 years ago

Also, it is possible that the memory buffer code is not needed at all. Simply setting the CURLOPT_NOSIGNAL flag appears to solve the problem. I leave it to your discretion how much of this patch to include. It was a fun distraction from the normal workday problems :)

Thanks for patron.

toland commented 12 years ago

Thank you! This looks great.