mysql2 0.2.17 → 0.2.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ree
6
+ before_script:
7
+ - "mysql -e 'create database test;' >/dev/null"
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.18 (December 6th, 2011)
4
+ * change mysql error detection strategy from using mysql_field_count to the more explicit mysql_errno
5
+ * bugfix to avoid race condition with active connections that error out
6
+ * revert back to using xmalloc/xfree for allocations
7
+ * avoid potentially unsafe Ruby C API usage w/o GVL
8
+ * reacquire GVL before retrying on EINTR on connect
9
+
3
10
  ## 0.2.17 (November 9th, 2011)
4
11
 
5
12
  ## 0.2.16 (November 9th, 2011)
@@ -46,6 +46,8 @@ struct nogvl_connect_args {
46
46
  struct nogvl_send_query_args {
47
47
  MYSQL *mysql;
48
48
  VALUE sql;
49
+ const char *sql_ptr;
50
+ long sql_len;
49
51
  mysql_client_wrapper *wrapper;
50
52
  };
51
53
 
@@ -112,12 +114,10 @@ static VALUE nogvl_connect(void *ptr) {
112
114
  struct nogvl_connect_args *args = ptr;
113
115
  MYSQL *client;
114
116
 
115
- do {
116
- client = mysql_real_connect(args->mysql, args->host,
117
- args->user, args->passwd,
118
- args->db, args->port, args->unix_socket,
119
- args->client_flag);
120
- } while (! client && errno == EINTR && (errno = 0) == 0);
117
+ client = mysql_real_connect(args->mysql, args->host,
118
+ args->user, args->passwd,
119
+ args->db, args->port, args->unix_socket,
120
+ args->client_flag);
121
121
 
122
122
  return client ? Qtrue : Qfalse;
123
123
  }
@@ -147,7 +147,7 @@ static VALUE nogvl_close(void *ptr) {
147
147
  #endif
148
148
 
149
149
  mysql_close(wrapper->client);
150
- free(wrapper->client);
150
+ xfree(wrapper->client);
151
151
  }
152
152
 
153
153
  return Qnil;
@@ -158,7 +158,7 @@ static void rb_mysql_client_free(void * ptr) {
158
158
 
159
159
  nogvl_close(wrapper);
160
160
 
161
- free(ptr);
161
+ xfree(ptr);
162
162
  }
163
163
 
164
164
  static VALUE allocate(VALUE klass) {
@@ -169,7 +169,7 @@ static VALUE allocate(VALUE klass) {
169
169
  wrapper->active = 0;
170
170
  wrapper->reconnect_enabled = 0;
171
171
  wrapper->closed = 1;
172
- wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
172
+ wrapper->client = (MYSQL*)xmalloc(sizeof(MYSQL));
173
173
  return obj;
174
174
  }
175
175
 
@@ -181,25 +181,26 @@ static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
181
181
  Check_Type(str, T_STRING);
182
182
 
183
183
  oldLen = RSTRING_LEN(str);
184
- newStr = malloc(oldLen*2+1);
184
+ newStr = xmalloc(oldLen*2+1);
185
185
 
186
186
  newLen = mysql_escape_string((char *)newStr, StringValuePtr(str), oldLen);
187
187
  if (newLen == oldLen) {
188
188
  // no need to return a new ruby string if nothing changed
189
- free(newStr);
189
+ xfree(newStr);
190
190
  return str;
191
191
  } else {
192
192
  rb_str = rb_str_new((const char*)newStr, newLen);
193
193
  #ifdef HAVE_RUBY_ENCODING_H
194
194
  rb_enc_copy(rb_str, str);
195
195
  #endif
196
- free(newStr);
196
+ xfree(newStr);
197
197
  return rb_str;
198
198
  }
199
199
  }
200
200
 
201
201
  static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
202
202
  struct nogvl_connect_args args;
203
+ VALUE rv;
203
204
  GET_CLIENT(self);
204
205
 
205
206
  args.host = NIL_P(host) ? "localhost" : StringValuePtr(host);
@@ -211,9 +212,14 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
211
212
  args.mysql = wrapper->client;
212
213
  args.client_flag = NUM2ULONG(flags);
213
214
 
214
- if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
215
- // unable to connect
216
- return rb_raise_mysql2_error(wrapper);
215
+ rv = rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0);
216
+ if (rv == Qfalse) {
217
+ while (rv == Qfalse && errno == EINTR) {
218
+ errno = 0;
219
+ rv = rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0);
220
+ }
221
+ if (rv == Qfalse)
222
+ return rb_raise_mysql2_error(wrapper);
217
223
  }
218
224
 
219
225
  return self;
@@ -243,10 +249,8 @@ static VALUE rb_mysql_client_close(VALUE self) {
243
249
  static VALUE nogvl_send_query(void *ptr) {
244
250
  struct nogvl_send_query_args *args = ptr;
245
251
  int rv;
246
- const char *sql = StringValuePtr(args->sql);
247
- long sql_len = RSTRING_LEN(args->sql);
248
252
 
249
- rv = mysql_send_query(args->mysql, sql, sql_len);
253
+ rv = mysql_send_query(args->mysql, args->sql_ptr, args->sql_len);
250
254
 
251
255
  return rv == 0 ? Qtrue : Qfalse;
252
256
  }
@@ -311,9 +315,11 @@ static VALUE rb_mysql_client_async_result(VALUE self) {
311
315
  result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
312
316
 
313
317
  if (result == NULL) {
314
- if (mysql_field_count(wrapper->client) != 0) {
318
+ if (mysql_errno(wrapper->client) != 0) {
319
+ MARK_CONN_INACTIVE(self);
315
320
  rb_raise_mysql2_error(wrapper);
316
321
  }
322
+ // no data and no error, so query was not a SELECT
317
323
  return Qnil;
318
324
  }
319
325
 
@@ -450,6 +456,8 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
450
456
  // ensure the string is in the encoding the connection is expecting
451
457
  args.sql = rb_str_export_to_enc(args.sql, conn_enc);
452
458
  #endif
459
+ args.sql_ptr = StringValuePtr(args.sql);
460
+ args.sql_len = RSTRING_LEN(args.sql);
453
461
 
454
462
  // see if this connection is still waiting on a result from a previous query
455
463
  if (wrapper->active == 0) {
@@ -502,12 +510,12 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
502
510
  #endif
503
511
 
504
512
  oldLen = RSTRING_LEN(str);
505
- newStr = malloc(oldLen*2+1);
513
+ newStr = xmalloc(oldLen*2+1);
506
514
 
507
515
  newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, StringValuePtr(str), oldLen);
508
516
  if (newLen == oldLen) {
509
517
  // no need to return a new ruby string if nothing changed
510
- free(newStr);
518
+ xfree(newStr);
511
519
  return str;
512
520
  } else {
513
521
  rb_str = rb_str_new((const char*)newStr, newLen);
@@ -517,7 +525,7 @@ static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
517
525
  rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
518
526
  }
519
527
  #endif
520
- free(newStr);
528
+ xfree(newStr);
521
529
  return rb_str;
522
530
  }
523
531
  }
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.2.17"
2
+ VERSION = "0.2.18"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- hash: 53
4
+ hash: 51
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 17
10
- version: 0.2.17
9
+ - 18
10
+ version: 0.2.18
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Lopez
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-09 00:00:00 -08:00
18
+ date: 2011-12-06 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -160,6 +160,7 @@ files:
160
160
  - .gitignore
161
161
  - .rspec
162
162
  - .rvmrc
163
+ - .travis.yml
163
164
  - CHANGELOG.md
164
165
  - Gemfile
165
166
  - MIT-LICENSE
@@ -237,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
237
238
  requirements: []
238
239
 
239
240
  rubyforge_project:
240
- rubygems_version: 1.6.2
241
+ rubygems_version: 1.3.9.3
241
242
  signing_key:
242
243
  specification_version: 3
243
244
  summary: A simple, fast Mysql library for Ruby, binding to libmysql