summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--gc.c14
-rw-r--r--version.h2
3 files changed, 24 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ef9f18bdc5..2a03620e4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Thu Jan 30 19:08:00 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_gc_finalize_deferred, rb_objspace_call_finalizer):
+ should use ATOMIC_EXCHANGE() to check the previous value.
+ [ruby-dev:44596] [Bug #5439]
+
+Thu Jan 30 19:08:00 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (slot_sweep, rb_gc_finalize_deferred)
+ (rb_objspace_call_finalizer, rb_gc): run finalizers
+ sequencially. [ruby-dev:44562]
+
Thu Jan 30 11:07:09 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c (CLASS_NAME): macro to wrap
diff --git a/gc.c b/gc.c
index 0f84e22966..c32a189dcc 100644
--- a/gc.c
+++ b/gc.c
@@ -377,6 +377,7 @@ typedef struct rb_objspace {
int dont_gc;
int dont_lazy_sweep;
int during_gc;
+ rb_atomic_t finalizing;
} flags;
struct {
st_table *table;
@@ -415,6 +416,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#define heaps_freed objspace->heap.freed
#define dont_gc objspace->flags.dont_gc
#define during_gc objspace->flags.during_gc
+#define finalizing objspace->flags.finalizing
#define finalizer_table objspace->final.table
#define deferred_final_list objspace->final.deferred
#define global_List objspace->global_list
@@ -2175,7 +2177,7 @@ slot_sweep(rb_objspace_t *objspace, struct heaps_slot *sweep_slot)
}
objspace->heap.final_num += final_num;
- if (deferred_final_list) {
+ if (deferred_final_list && !finalizing) {
rb_thread_t *th = GET_THREAD();
if (th) {
RUBY_VM_SET_FINALIZER_INTERRUPT(th);
@@ -3053,7 +3055,10 @@ finalize_deferred(rb_objspace_t *objspace)
void
rb_gc_finalize_deferred(void)
{
- finalize_deferred(&rb_objspace);
+ rb_objspace_t *objspace = &rb_objspace;
+ if (ATOMIC_EXCHANGE(finalizing, 1)) return;
+ finalize_deferred(objspace);
+ ATOMIC_SET(finalizing, 0);
}
struct force_finalize_list {
@@ -3093,6 +3098,8 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
finalize_deferred(objspace);
assert(deferred_final_list == 0);
+ if (ATOMIC_EXCHANGE(finalizing, 1)) return;
+
/* force to run finalizer */
while (finalizer_table->num_entries) {
struct force_finalize_list *list = 0;
@@ -3147,6 +3154,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
st_free_table(finalizer_table);
finalizer_table = 0;
+ ATOMIC_SET(finalizing, 0);
}
void
@@ -3154,7 +3162,7 @@ rb_gc(void)
{
rb_objspace_t *objspace = &rb_objspace;
garbage_collect(objspace);
- finalize_deferred(objspace);
+ if (!finalizing) finalize_deferred(objspace);
free_unused_heaps(objspace);
}
diff --git a/version.h b/version.h
index cba4872a64..c069e2c1e0 100644
--- a/version.h
+++ b/version.h
@@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 505
+#define RUBY_PATCHLEVEL 506
#define RUBY_RELEASE_DATE "2014-01-30"
#define RUBY_RELEASE_YEAR 2014