
Issue #20863 has been updated by ko1 (Koichi Sasada). Quoted from `rb_thread_call_without_gvl` doc: ``` * NOTE: You can not execute most of Ruby C API and touch Ruby * objects in `func()' and `ubf()', including raising an * exception, because current thread doesn't acquire GVL * (it causes synchronization problems). If you need to * call ruby functions either use rb_thread_call_with_gvl() * or read source code of C APIs and confirm safety by * yourself. * * NOTE: In short, this API is difficult to use safely. I recommend you * use other ways if you have. We lack experiences to use this API. * Please report your problem related on it. * * NOTE: Releasing GVL and re-acquiring GVL may be expensive operations * for a short running `func()'. Be sure to benchmark and use this * mechanism when `func()' consumes enough time. * * Safe C API: * * rb_thread_interrupted() - check interrupt flag * * ruby_xmalloc(), ruby_xrealloc(), ruby_xfree() - * they will work without GVL, and may acquire GVL when GC is needed. ``` Again: ``` * NOTE: In short, this API is difficult to use safely. I recommend you * use other ways if you have. We lack experiences to use this API. * Please report your problem related on it. ``` ---------------------------------------- Bug #20863: `zlib.c` calls `rb_str_set_len` and `rb_str_modify_expand`(and others) without holding the GVL. https://bugs.ruby-lang.org/issues/20863#change-110505 * Author: ioquatix (Samuel Williams) * Status: Open * Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN ---------------------------------------- ## Background I was working on https://bugs.ruby-lang.org/issues/20876 and was investigating some problems with `zlib.c` and GVL, and noticed that `zstream_run_func` is executed without the GVL, but can invoke various `rb_` string functions. Those functions in turn can invoke `rb_raise` and generally look problematic. However, maybe by luck, such code path does not appear to be invoked in typical usage. However, even so, it is possible to cause `zstream_run_func` to segfault by a carefully crafted program which causes the internal buffer to be resized while the GVL is released: https://github.com/ruby/zlib/pull/88#issuecomment-2455772054 ## Proposal I would like to modify `zlib.c` to only release the GVL around the CPU intensive compression/decompression operation: https://github.com/ruby/zlib/pull/88 In addition, I identified several more improvements to prevent segfaults and other related failures: - Use `rb_str_locktemp` to prevent the `z->buf` changing size while in use by the `rb_nogvl` code. - Expand the mutex to protect `#deflate` and `#inflate` completely, not just the internal operation. In order to catch these issues earlier and find other bugs like this, I recommend we introduce additional checks: https://bugs.ruby-lang.org/issues/20877 -- https://bugs.ruby-lang.org/