Skip to content

Commit

Permalink
* remove CURLAUTH_ANY as the default for authentication setting too m…
Browse files Browse the repository at this point in the history
…any services in the world don't respond correctly with a 401 but instead 403 so the option rarely works as we'd hope.

* use the memory address as the key to correctly keep a hash of active easy handles alive in the multi handle.  This should resolve existing reports of memory leaks as well as crashes under some conditions
  • Loading branch information
taf2 committed Dec 14, 2015
1 parent 04d2421 commit 4caf18a
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 14 deletions.
5 changes: 3 additions & 2 deletions curb.gemspec
@@ -1,15 +1,16 @@
Gem::Specification.new do |s|
s.name = "curb"
s.authors = ["Ross Bamford", "Todd A. Fisher"]
s.version = '0.8.8'
s.date = '2015-04-08'
s.version = '0.9.0'
s.date = '2015-12-14'
s.description = %q{Curb (probably CUrl-RuBy or something) provides Ruby-language bindings for the libcurl(3), a fully-featured client-side URL transfer library. cURL and libcurl live at http://curl.haxx.se/}
s.email = 'todd.fisher@gmail.com'
s.extra_rdoc_files = ['LICENSE', 'README.markdown']

s.files = ["LICENSE", "README.markdown", "Rakefile", "doc.rb", "ext/extconf.rb", "lib/curb.rb", "lib/curl/easy.rb", "lib/curl/multi.rb", "lib/curl.rb", "ext/curb.c", "ext/curb_easy.c", "ext/curb_errors.c", "ext/curb_multi.c", "ext/curb_postfield.c", "ext/curb_upload.c", "ext/curb.h", "ext/curb_easy.h", "ext/curb_errors.h", "ext/curb_macros.h", "ext/curb_multi.h", "ext/curb_postfield.h", "ext/curb_upload.h"]
#### Load-time details
s.require_paths = ['lib','ext']
s.rubyforge_project = 'curb'
s.summary = %q{Ruby libcurl bindings}
s.test_files = ["tests/alltests.rb", "tests/bug_crash_on_debug.rb", "tests/bug_crash_on_progress.rb", "tests/bug_curb_easy_blocks_ruby_threads.rb", "tests/bug_curb_easy_post_with_string_no_content_length_header.rb", "tests/bug_instance_post_differs_from_class_post.rb", "tests/bug_issue102.rb", "tests/bug_multi_segfault.rb", "tests/bug_postfields_crash.rb", "tests/bug_postfields_crash2.rb", "tests/bug_require_last_or_segfault.rb", "tests/bugtests.rb", "tests/helper.rb", "tests/mem_check.rb", "tests/require_last_or_segfault_script.rb", "tests/signals.rb", "tests/tc_curl.rb", "tests/tc_curl_download.rb", "tests/tc_curl_easy.rb", "tests/tc_curl_easy_setopt.rb", "tests/tc_curl_multi.rb", "tests/tc_curl_postfield.rb", "tests/timeout.rb", "tests/timeout_server.rb", "tests/unittests.rb"]

Expand Down
8 changes: 4 additions & 4 deletions ext/curb.h
Expand Up @@ -20,11 +20,11 @@
#include "curb_macros.h"

// These should be managed from the Rake 'release' task.
#define CURB_VERSION "0.8.9"
#define CURB_VER_NUM 809
#define CURB_VERSION "0.9.0"
#define CURB_VER_NUM 900
#define CURB_VER_MAJ 0
#define CURB_VER_MIN 8
#define CURB_VER_MIC 9
#define CURB_VER_MIN 0
#define CURB_VER_MIC 0
#define CURB_VER_PATCH 0


Expand Down
7 changes: 3 additions & 4 deletions ext/curb_easy.c
Expand Up @@ -2160,11 +2160,12 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
#endif
}

/*
* NOTE: we used to set CURLAUTH_ANY but see: http://curl.haxx.se/mail/lib-2015-06/0033.html
*/
if (rbce->http_auth_types > 0) {
#if LIBCURL_VERSION_NUM >= 0x070a06
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, rbce->http_auth_types);
} else {
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
#else
rb_warn("Installed libcurl is too old to support http_auth_types");
#endif
Expand All @@ -2173,8 +2174,6 @@ VALUE ruby_curl_easy_setup(ruby_curl_easy *rbce) {
if (rbce->proxy_auth_types > 0) {
#if LIBCURL_VERSION_NUM >= 0x070a07
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, rbce->proxy_auth_types);
} else {
curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
#else
rb_warn("Installed libcurl is too old to support proxy_auth_types");
#endif
Expand Down
19 changes: 15 additions & 4 deletions ext/curb_multi.c
Expand Up @@ -227,12 +227,19 @@ static VALUE ruby_curl_multi_pipeline(VALUE self, VALUE onoff) {
*/
VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
CURLMcode mcode;
VALUE r;
ruby_curl_easy *rbce;
ruby_curl_multi *rbcm;

Data_Get_Struct(self, ruby_curl_multi, rbcm);
Data_Get_Struct(easy, ruby_curl_easy, rbce);

// check if this curl handle has been added before adding again
r = rb_hash_aref(rbcm->requests, INT2NUM((int)rbce->curl));
if ( r != Qnil ) {
return Qnil;
}

/* setup the easy handle */
ruby_curl_easy_setup( rbce );

Expand All @@ -247,7 +254,7 @@ VALUE ruby_curl_multi_add(VALUE self, VALUE easy) {
* If this number is not correct, the next call to curl_multi_perform will correct it. */
rbcm->running++;

rb_hash_aset( rbcm->requests, easy, easy );
rb_hash_aset( rbcm->requests, INT2NUM((int)rbce->curl), easy );

return self;
}
Expand Down Expand Up @@ -282,6 +289,12 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {

Data_Get_Struct(easy, ruby_curl_easy, rbce);

// check if this curl handle has been added before removing
r = rb_hash_aref(rbcm->requests, INT2NUM((int)rbce->curl));
if ( r == Qnil ) {
return;
}

result = curl_multi_remove_handle(rbcm->handle, rbce->curl);
if (result != 0) {
raise_curl_multi_error_exception(result);
Expand All @@ -292,7 +305,7 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy) {
ruby_curl_easy_cleanup( easy, rbce );

// active should equal INT2FIX(RHASH(rbcm->requests)->tbl->num_entries)
r = rb_hash_delete( rbcm->requests, easy );
r = rb_hash_delete( rbcm->requests, INT2NUM((int)rbce->curl) );
if( r != easy || r == Qnil ) {
rb_warn("Possibly lost track of Curl::Easy VALUE, it may not be reclaimed by GC");
}
Expand Down Expand Up @@ -408,8 +421,6 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res

if (val == Qfalse) {
rb_warn("uncaught exception from callback");
// exception was raised?
//fprintf(stderr, "exception raised from callback\n");
}

}
Expand Down
1 change: 1 addition & 0 deletions lib/curl/easy.rb
Expand Up @@ -66,6 +66,7 @@ def perform
self.multi = Curl::Multi.new if self.multi.nil?
self.multi.add self
ret = self.multi.perform
self.multi.remove self

if self.last_result != 0 && self.on_failure.nil?
error = Curl::Easy.error(self.last_result)
Expand Down

0 comments on commit 4caf18a

Please sign in to comment.