Bug #16503
closed"ret: 2, hash modified during iteration" error in Ruby 2.7.0
Description
I am running a Rails app on Heroku. After upgrading to Ruby 2.7, I sometimes get ret: 2, hash modified during iteration
error.
The same issue is reported here (I'm using meta-tags gem too):
https://github.com/kpumuk/meta-tags/issues/209
This gem deletes elements while iterating hash (HashWithIndifferentAccess actually), so I guess it might involve this error:
https://github.com/kpumuk/meta-tags/blob/v2.13.0/lib/meta_tags/renderer.rb#L168
https://github.com/kpumuk/meta-tags/blob/v2.13.0/lib/meta_tags/renderer.rb#L181
https://github.com/kpumuk/meta-tags/blob/v2.13.0/lib/meta_tags/meta_tags_collection.rb#L85
However, this error does not occur every time (sometimes works, sometimes fails), and it didn't occur in Ruby 2.6. So I'm wondering why. Do you have any idea on this?
Updated by ko1 (Koichi Sasada) over 3 years ago
Could you make reproducible script?
Updated by ko1 (Koichi Sasada) over 3 years ago
All right. I got a script:
loop{
h = {a:1, b:2, c:3, d:4, e:5, f:6, g:7, h:8}
h.each{|k,v| GC.start; h.delete(k)}
}
The patch is:
diff --git a/hash.c b/hash.c
index 878f2b1790..644f85d6da 100644
--- a/hash.c
+++ b/hash.c
@@ -974,6 +974,7 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg
switch (retval) {
case ST_CHECK: {
+ pair = RHASH_AR_TABLE_REF(hash, i);
if (pair->key == never) break;
ret = ar_find_entry_hint(hash, hint, key);
if (ret == RHASH_AR_TABLE_MAX_BOUND) {
This patch should be back-ported for Ruby 2.6.
Thank you for your report.
Updated by ko1 (Koichi Sasada) over 3 years ago
This patch should be back-ported for Ruby 2.6.
sorry I mean 2.7. 2.6 doesn't have this problem.
Updated by ko1 (Koichi Sasada) over 3 years ago
- Status changed from Open to Closed
350dafd56a9cff58d36303aeb7515ab41c5dbbb3
Updated by jnchito (Junichi Ito) over 3 years ago
Thank you very much for your quick fix. I left a comment in the meta-tags issue:
Updated by nobu (Nobuyoshi Nakada) over 3 years ago
- Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED
Updated by naruse (Yui NARUSE) over 3 years ago
- Backport changed from 2.5: DONTNEED, 2.6: DONTNEED, 2.7: REQUIRED to 2.5: DONTNEED, 2.6: DONTNEED, 2.7: DONE
ruby_2_7 8e8841f6bf58031a1fe5b0dbacb5a1fb442102df.