[#105450] [Ruby master Feature#18228] Add a `timeout` option to `IO.copy_stream` — "byroot (Jean Boussier)" <noreply@...>
SXNzdWUgIzE4MjI4IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGJ5cm9vdCAoSmVhbiBCb3Vzc2llciku
11 messages
2021/09/27
[ruby-core:105163] [Ruby master Feature#18143] Add a new method to change GC.stress only in the given block such as GC.with_stress(flag) {...}
From:
"byroot (Jean Boussier)" <noreply@...>
Date:
2021-09-06 22:29:35 UTC
List:
ruby-core #105163
Issue #18143 has been updated by byroot (Jean Boussier).
NB: it was mostly a quick thought, I don't plan to formally propose it.
That being said:
> need to be a keyword though to be efficient
I don't quite see why a keyword would be needed for efficiency, neither do I see why it would need to be particularly efficient. This pattern is generally used very high up the stack and rarely in hotspots. Even a pure Ruby implementation would be fine IMHO.
> it could conflict with existing `with` methods.
If it's defined in `Object` or `Kernel`, any existing `with` method would override it, so I don't see how it could conflict. You could also argue that it would mostly be useful on classes and module and define it in `Module`.
> IMHO it looks much like Python's with keyword
Only very superficially. Python's `with` protocol allow you to emulate the Ruby pattern:
```
def foo
# do something: Python's `__enter__()`
yield
ensure
# cleanup: Python's `__exit__()`
end
```
> I feel blocks are the natural replacement in Ruby.
Well, that's what this suggestion is, a block. It's just a general solution to setting and restoring an attribute instead of an ad hoc solution for just `GC.stress`.
----------------------------------------
Feature #18143: Add a new method to change GC.stress only in the given block such as GC.with_stress(flag) {...}
https://bugs.ruby-lang.org/issues/18143#change-93569
* Author: kou (Kouhei Sutou)
* Status: Open
* Priority: Normal
----------------------------------------
`GC.stress = true` is useful for detecting GC related crashes. We can use it for debugging GC related problems and testing the problem is solved.
Generally, we need to enable stress mode before the target code block and disable stress mode after the target code block:
```ruby
GC.stress = true
# ... something buggy codes ...
GC.stress = false
```
Or we just enable stress mode before the target code block when the target code block causes a crash:
```ruby
GC.stress = true
# ... something crash codes ...
```
In test code, we must disable stress mode because stress mode slows down test execution:
```ruby
def test_gc
GC.stress = true
# ... GC related code ...
ensure
GC.stress = false
end
```
We have an utility method in CRuby's test utility: `EnvUtil.#under_gc_stress`:
https://github.com/ruby/ruby/blob/ab63f6d8543903f177c46634f38e5428655f003b/tool/lib/envutil.rb#L236-L242
```ruby
def under_gc_stress(stress = true)
stress, GC.stress = GC.stress, stress
yield
ensure
GC.stress = stress
end
module_function :under_gc_stress
```
This feature is useful not only CRuby's test but also other libraries test and debugging a program that has a GC related problem.
How about adding a new singleton method that changes stress mode only in the given block? If we have the method, we don't need to implement a small utility method multiple times for the feature.
API candidates:
`GC.with_stress(flag) {...}`:
```ruby
module GC
def self.with_stress(flag)
flag_old = stress
self.stress = flag
yield
ensure
self.stress = flag_old
end
end
```
`GC.under_stress {...}`:
```ruby
module GC
def self.under_stress
flag_old = stress
self.stress = true
yield
ensure
self.stress = flag_old
end
end
```
`GC.stress(flag = true) {...}`:
```ruby
module GC
def stress flag = true
if block_given?
flag_old = Primitive.gc_stress_get
begin
GC.stress = flag
ensure
GC.stress = flag_old
end
else
Primitive.gc_stress_get
end
end
end
```
Note:
* Disadvantage is, `GC.stress` is a getter method and `GC.stress do end` is setter method. It can be confusing.
* @nobu also pointed out that the block is just ignored on the older Ruby versions.
Source of implementation and some discussions: https://github.com/ruby/ruby/pull/4793
Background:
I'm maintaining some default gems. They have copy of `EnvUtil` but I don't want to have it for maintainability. If Ruby provides this feature by default, we can use it instead of copying `EnvUtil`. I know that I need to implement/copy the feature in each default gem until Ruby 3.0 reaches EOL. But we don't have the feature now, I need to copy `EnvUtil` forever.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>