oj 2.2.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oj might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 964ef71e46a6e9c4fb8c734c520e81030a2c76e8
4
- data.tar.gz: 31d2779214092e6b11ccdbfa5047abdb96dd0b31
3
+ metadata.gz: 01dd99731dba1d9feeffe3135e41b282718c6342
4
+ data.tar.gz: 0c635bcad7be8c0a8b86a074dc2cc42946a4938a
5
5
  SHA512:
6
- metadata.gz: aa82d27d48917343e1d1737804a84bcf578a47f2b1eef6f05fe59e2a68a1c95ebddf7307fc52dd59224f650c04245cbf98df9ab132d7562506bcc563a06becc0
7
- data.tar.gz: dd0354a15f36b3f9337376832df8f051addfa1240eaaeba452c9d0a99a81f77c415e89ef4a1e6e677edde321384b1bd68127fa964e846f07b2e76ff7e185547c
6
+ metadata.gz: 9cabf96957642d870530a33ed6b4236505d6e67e06d6cddbb7f2b29e2dcc567a12b844a5fe7abe317bb0f3a65cccadf81240c8af23aa4ff7c45363c744bfc045
7
+ data.tar.gz: 2e2b979fbe2a517b04bca9eb3144b9c3edfeccfd33a3849b4d175a882036b3dff2631de3c888fa608fdbc13a1f3e3b97cbd71fef3f5b87d3ac27074d70606109
data/README.md CHANGED
@@ -20,6 +20,12 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
20
20
 
21
21
  [![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
22
22
 
23
+ ### Current Release 2.2.2
24
+
25
+ - Added mutex support for Windows.
26
+
27
+ - Protected SCP parser for GC.
28
+
23
29
  ### Current Release 2.2.1
24
30
 
25
31
  - Made all VALUEs in parse volatile to avoid garbage collection while in use.
@@ -31,7 +31,8 @@ dflags = {
31
31
  'HAS_TOP_LEVEL_ST_H' => ('ree' == type || ('ruby' == type && '1' == version[0] && '8' == version[1])) ? 1 : 0,
32
32
  'NEEDS_RATIONAL' => ('1' == version[0] && '8' == version[1]) ? 1 : 0,
33
33
  'IS_WINDOWS' => is_windows ? 1 : 0,
34
- 'SAFE_CACHE' => is_windows ? 0 : 1,
34
+ 'USE_PTHREAD_MUTEX' => is_windows ? 0 : 1,
35
+ 'USE_RB_MUTEX' => (is_windows && !('1' == version[0] && '8' == version[1])) ? 1 : 0,
35
36
  }
36
37
  # This is a monster hack to get around issues with 1.9.3-p0 on CentOS 5.4. SO
37
38
  # some reason math.h and string.h contents are not processed. Might be a
@@ -263,8 +263,10 @@ set_obj_ivar(Val parent, const char *key, size_t klen, VALUE value) {
263
263
  rb_funcall(parent->val, rb_intern("set_backtrace"), 1, value);
264
264
  }
265
265
  }
266
- #if SAFE_CACHE
266
+ #if USE_PTHREAD_MUTEX
267
267
  pthread_mutex_lock(&oj_cache_mutex);
268
+ #elif USE_RB_MUTEX
269
+ rb_mutex_lock(oj_cache_mutex);
268
270
  #endif
269
271
  if (0 == (var_id = oj_attr_hash_get(key, klen, &slot))) {
270
272
  char attr[256];
@@ -295,8 +297,10 @@ set_obj_ivar(Val parent, const char *key, size_t klen, VALUE value) {
295
297
  }
296
298
  *slot = var_id;
297
299
  }
298
- #if SAFE_CACHE
300
+ #if USE_PTHREAD_MUTEX
299
301
  pthread_mutex_unlock(&oj_cache_mutex);
302
+ #elif USE_RB_MUTEX
303
+ rb_mutex_unlock(oj_cache_mutex);
300
304
  #endif
301
305
  rb_ivar_set(parent->val, var_id, value);
302
306
  }
@@ -129,8 +129,10 @@ rb_encoding *oj_utf8_encoding = 0;
129
129
  VALUE oj_utf8_encoding = Qnil;
130
130
  #endif
131
131
 
132
- #if SAFE_CACHE
133
- pthread_mutex_t oj_cache_mutex; // only used if SAFE_CACHE defined
132
+ #if USE_PTHREAD_MUTEX
133
+ pthread_mutex_t oj_cache_mutex;
134
+ #elif USE_RB_MUTEX
135
+ VALUE oj_cache_mutex = Qnil;
134
136
  #endif
135
137
  static const char json_class[] = "json_class";
136
138
 
@@ -1269,8 +1271,11 @@ void Init_oj() {
1269
1271
  oj_hash_init();
1270
1272
  oj_odd_init();
1271
1273
 
1272
- #if SAFE_CACHE
1274
+ #if USE_PTHREAD_MUTEX
1273
1275
  pthread_mutex_init(&oj_cache_mutex, 0);
1276
+ #elif USE_RB_MUTEX
1277
+ oj_cache_mutex = rb_mutex_new();
1278
+ rb_gc_register_address(&oj_cache_mutex);
1274
1279
  #endif
1275
1280
  oj_init_doc();
1276
1281
  }
@@ -46,7 +46,8 @@ extern "C" {
46
46
  #endif
47
47
 
48
48
  #include "stdint.h"
49
- #if SAFE_CACHE
49
+
50
+ #if USE_PTHREAD_MUTEX
50
51
  #include <pthread.h>
51
52
  #endif
52
53
  #include "cache8.h"
@@ -224,9 +225,12 @@ extern ID oj_tv_usec_id;
224
225
  extern ID oj_utc_offset_id;
225
226
  extern ID oj_write_id;
226
227
 
227
- #if SAFE_CACHE
228
+ #if USE_PTHREAD_MUTEX
228
229
  extern pthread_mutex_t oj_cache_mutex;
230
+ #elif USE_RB_MUTEX
231
+ extern VALUE oj_cache_mutex;
229
232
  #endif
233
+
230
234
  #if defined(__cplusplus)
231
235
  #if 0
232
236
  { /* satisfy cc-mode */
@@ -569,11 +569,8 @@ colon(ParseInfo pi) {
569
569
 
570
570
  void
571
571
  oj_parse2(ParseInfo pi) {
572
- volatile VALUE rstack = Qnil;
573
-
574
572
  pi->cur = pi->json;
575
573
  err_init(&pi->err);
576
- rstack = oj_stack_init(&pi->stack);
577
574
  while (1) {
578
575
  next_non_white(pi);
579
576
  switch (*pi->cur++) {
@@ -647,7 +644,7 @@ oj_parse2(ParseInfo pi) {
647
644
 
648
645
  VALUE
649
646
  oj_num_as_value(NumInfo ni) {
650
- volatile VALUE rnum = Qnil;
647
+ VALUE rnum = Qnil;
651
648
 
652
649
  if (ni->infinity) {
653
650
  if (ni->neg) {
@@ -721,7 +718,8 @@ VALUE
721
718
  oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
722
719
  char *buf = 0;
723
720
  volatile VALUE input;
724
- volatile VALUE result = Qnil;
721
+ volatile VALUE wrapped_stack;
722
+ VALUE result = Qnil;
725
723
  int line = 0;
726
724
  int free_json = 0;
727
725
 
@@ -782,10 +780,14 @@ oj_pi_parse(int argc, VALUE *argv, ParseInfo pi, char *json) {
782
780
  pi->circ_array = 0;
783
781
  }
784
782
  // GC can run at any time. When it runs any Object created by C will be
785
- // freed. This usually only happens with large files but it does happen and
786
- // it happens more frequently on Ruby 1.8.7.
783
+ // freed. We protect against this by wrapping the value stack in a ruby
784
+ // data object and poviding a mark function for ruby objects on the
785
+ // value stack (while it is in scope).
786
+ wrapped_stack = oj_stack_init(&pi->stack);
787
787
  rb_protect(protect_parse, (VALUE)pi, &line);
788
788
  result = stack_head_val(&pi->stack);
789
+ DATA_PTR(wrapped_stack) = 0;
790
+
789
791
  // proceed with cleanup
790
792
  if (0 != pi->circ_array) {
791
793
  oj_circ_array_free(pi->circ_array);
@@ -31,7 +31,7 @@
31
31
  #include <stdlib.h>
32
32
  #include <stdio.h>
33
33
  #include <string.h>
34
- #if SAFE_CACHE
34
+ #if USE_PTHREAD_MUTEX
35
35
  #include <pthread.h>
36
36
  #endif
37
37
 
@@ -102,16 +102,20 @@ oj_name2class(ParseInfo pi, const char *name, size_t len, int auto_define) {
102
102
  if (No == pi->options.class_cache) {
103
103
  return resolve_classpath(pi, name, len, auto_define);
104
104
  }
105
- #if SAFE_CACHE
105
+ #if USE_PTHREAD_MUTEX
106
106
  pthread_mutex_lock(&oj_cache_mutex);
107
+ #elif USE_RB_MUTEX
108
+ rb_mutex_lock(oj_cache_mutex);
107
109
  #endif
108
110
  if (Qnil == (clas = oj_class_hash_get(name, len, &slot))) {
109
111
  if (Qundef != (clas = resolve_classpath(pi, name, len, auto_define))) {
110
112
  *slot = clas;
111
113
  }
112
114
  }
113
- #if SAFE_CACHE
115
+ #if USE_PTHREAD_MUTEX
114
116
  pthread_mutex_unlock(&oj_cache_mutex);
117
+ #elif USE_RB_MUTEX
118
+ rb_mutex_unlock(oj_cache_mutex);
115
119
  #endif
116
120
  return clas;
117
121
  }
@@ -198,6 +198,7 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
198
198
  char *buf = 0;
199
199
  VALUE input;
200
200
  VALUE handler;
201
+ volatile VALUE wrapped_stack;
201
202
  int line = 0;
202
203
 
203
204
  if (argc < 2) {
@@ -252,8 +253,8 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
252
253
  if (rb_type(input) == T_STRING) {
253
254
  pi.json = StringValuePtr(input);
254
255
  } else {
255
- VALUE clas = rb_obj_class(input);
256
- VALUE s;
256
+ VALUE clas = rb_obj_class(input);
257
+ volatile VALUE s;
257
258
 
258
259
  if (oj_stringio_class == clas) {
259
260
  s = rb_funcall2(input, oj_string_id, 0, 0);
@@ -285,8 +286,9 @@ oj_sc_parse(int argc, VALUE *argv, VALUE self) {
285
286
  rb_raise(rb_eArgError, "saj_parse() expected a String or IO Object.");
286
287
  }
287
288
  }
289
+ wrapped_stack = oj_stack_init(&pi.stack);
288
290
  rb_protect(protect_parse, (VALUE)&pi, &line);
289
- //oj_parse2(&pi);
291
+ DATA_PTR(wrapped_stack) = NULL;
290
292
  if (0 != buf) {
291
293
  xfree(buf);
292
294
  }
@@ -36,18 +36,33 @@ mark(void *ptr) {
36
36
  ValStack stack = (ValStack)ptr;
37
37
  Val v;
38
38
 
39
+ if (ptr == NULL) return;
40
+
41
+ #if USE_PTHREAD_MUTEX
39
42
  pthread_mutex_lock(&stack->mutex);
43
+ #elif USE_RB_MUTEX
44
+ rb_mutex_lock(stack->mutex);
45
+ rb_gc_mark(stack->mutex);
46
+ #endif
40
47
  for (v = stack->head; v < stack->tail; v++) {
41
48
  if (Qnil != v->val && Qundef != v->val) {
42
49
  rb_gc_mark(v->val);
43
50
  }
44
51
  }
52
+ #if USE_PTHREAD_MUTEX
45
53
  pthread_mutex_unlock(&stack->mutex);
54
+ #elif USE_RB_MUTEX
55
+ rb_mutex_unlock(stack->mutex);
56
+ #endif
46
57
  }
47
58
 
48
59
  VALUE
49
60
  oj_stack_init(ValStack stack) {
61
+ #if USE_PTHREAD_MUTEX
50
62
  pthread_mutex_init(&stack->mutex, 0);
63
+ #elif USE_RB_MUTEX
64
+ stack->mutex = rb_mutex_new();
65
+ #endif
51
66
  stack->head = stack->base;
52
67
  stack->end = stack->base + sizeof(stack->base) / sizeof(struct _Val);
53
68
  stack->tail = stack->head;
@@ -68,7 +68,13 @@ typedef struct _ValStack {
68
68
  Val head; // current stack
69
69
  Val end; // stack end
70
70
  Val tail; // pointer to one past last element name on stack
71
+
72
+ #if USE_PTHREAD_MUTEX
71
73
  pthread_mutex_t mutex;
74
+ #elif USE_RB_MUTEX
75
+ VALUE mutex;
76
+ #endif
77
+
72
78
  } *ValStack;
73
79
 
74
80
  extern VALUE oj_stack_init(ValStack stack);
@@ -100,11 +106,19 @@ stack_push(ValStack stack, VALUE val, ValNext next) {
100
106
  } else {
101
107
  REALLOC_N(head, struct _Val, len + STACK_INC);
102
108
  }
109
+ #if USE_PTHREAD_MUTEX
103
110
  pthread_mutex_lock(&stack->mutex);
111
+ #elif USE_RB_MUTEX
112
+ rb_mutex_lock(stack->mutex);
113
+ #endif
104
114
  stack->head = head;
105
115
  stack->tail = stack->head + toff;
106
116
  stack->end = stack->head + len + STACK_INC;
117
+ #if USE_PTHREAD_MUTEX
107
118
  pthread_mutex_unlock(&stack->mutex);
119
+ #elif USE_RB_MUTEX
120
+ rb_mutex_unlock(stack->mutex);
121
+ #endif
108
122
  }
109
123
  stack->tail->val = val;
110
124
  stack->tail->next = next;
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.2.1'
4
+ VERSION = '2.2.2'
5
5
  end
@@ -53,13 +53,16 @@ $obj = {
53
53
  'i' => [[[[[[[nil]]]]]]] # deep array, again, not that deep
54
54
  }
55
55
 
56
+ $obj = [$obj]*10000
57
+
56
58
  Oj.default_options = { :indent => 2, :mode => :compat }
57
59
 
58
60
  $json = Oj.dump($obj, :mode => :compat)
59
61
 
60
- 1000000.times { |i|
61
- print(".") if (0 == i % 10000)
62
- Oj.compat_load($json)
62
+ $result = nil
63
+ 100.times { |i|
64
+ print(".") if (0 == i % 10)
65
+ $result = Oj.compat_load($json)
63
66
  }
64
67
 
65
68
 
@@ -217,7 +217,7 @@ class ScpTest < ::Test::Unit::TestCase
217
217
  begin
218
218
  Oj.sc_parse(handler, json)
219
219
  rescue Exception => e
220
- assert_equal("unexpected character at line 1, column 6 [parse.c:639]", e.message)
220
+ assert_equal("unexpected character at line 1, column 6 [parse.c:636]", e.message)
221
221
  end
222
222
  end
223
223
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-15 00:00:00.000000000 Z
11
+ date: 2013-11-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'The fastest JSON parser and object serializer. '
14
14
  email: peter@ohler.com