ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "parker (Parker Finch)" <noreply@ruby-lang.org>
To: ruby-core@neon.ruby-lang.org
Subject: [ruby-core:110292] [Ruby master Bug#19041] Weakref is still alive after major garbage collection
Date: Fri, 14 Oct 2022 20:04:21 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-99577.20221014200421.15511@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-19041.20221006190316.15511@ruby-lang.org

Issue #19041 has been updated by parker (Parker Finch).


Thanks for that explanation @tenderlovemaking, it helps and I truly appreciate it!

One misunderstanding I had was that I was thinking about this in terms of the Ruby VM. But it seems like garbage collection actually occurs down at the machine level (which makes much more sense now that I think about it) and that's why we're dealing with registers. (And the stack we're talking about is the C stack and not the Ruby VM stack.)

The recommendation to take a look at [RB_GC_GUARD](https://github.com/ruby/ruby/blob/cbd3d655745564e3c33a29a5625ac30b4d69fb29/include/ruby/internal/memory.h#L110-L172) was helpful as well, that's a great comment there.

I'm still curious _why_ calling `#weakref_alive?` on the `WeakRef` seems to put the underlying `Object` (that the `WeakRef` delegates to) in a register or on the stack. But the fact that this is happening so close to the actual machine makes it seem like it would be tricky to figure out.

Anyway, I'll keep learning more about how memory management works, thank you for the info here! I think the docs are fine as-is, so it makes sense to me to close this one.

Thank you all for your time and explanations!

----------------------------------------
Bug #19041: Weakref is still alive after major garbage collection
https://bugs.ruby-lang.org/issues/19041#change-99577

* Author: parker (Parker Finch)
* Status: Closed
* Priority: Normal
* ruby -v: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
I am able to get into an infinite loop waiting for garbage collection to take a WeakRef.

### Reproduction Process
The following script prints a "0", then a "1", and then hangs forever. I expect it to keep printing numbers.
```
require "weakref"

iterations = 0

loop do
  print "\r#{iterations}"
  obj = WeakRef.new(Object.new)
  GC.start while obj.weakref_alive?
  iterations += 1
end
```

### Ruby Version
I have tested this on Ruby 3.1.2, 3.1.0, 3.0.4, 3.0.0, 2.7.6, and 2.7.0 on macOS. All exhibit this behavior.

### Further Investigation
#### Sleeping
Sleeping before the garbage collection allows the loop to continue. The below exhibits the expected behavior:
```
require "weakref"

iterations = 0

loop do
  print "\r#{iterations}"
  obj = WeakRef.new(Object.new)
  (sleep(0.5); GC.start) while obj.weakref_alive?
  iterations += 1
end
```

However, sleeping _after_ the garbage collection still shows the buggy behavior (loop hangs):
```
require "weakref"

iterations = 0

loop do
  print "\r#{iterations}"
  obj = WeakRef.new(Object.new)
  (GC.start; sleep(0.5)) while obj.weakref_alive?
  iterations += 1
end
```

#### Running Garbage Collection Multiple Times
Explicitly running garbage collection multiple times allows the loop to continue. This has the expected behavior, more numbers continue to be printed:
```
require "weakref"

iterations = 0

loop do
  print "\r#{iterations}"
  obj = WeakRef.new(Object.new)
  while obj.weakref_alive?
    GC.start
    GC.start
    GC.start
  end
  iterations += 1
end
```

However, with certain rubies, running those garbage collection calls in a `times` block prevents even a single iteration from completing. The following prints only "0" with ruby 3.0.4 on macOS, ruby 2.7.6 on macOS, and ruby 3.1.2 on linux (`ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]` on a virtual machine). It shows the expected behavior on ruby 3.1.2 on macOS.
```
require "weakref"

iterations = 0

loop do
  print "\r#{iterations}"
  obj = WeakRef.new(Object.new)
  3.times { GC.start } while obj.weakref_alive?
  iterations += 1
end
```



-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2022-10-14 20:04 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-06 19:03 [ruby-core:110218] [Ruby master Bug#19041] Weakref is still alive after major garbage collection parker (Parker Finch)
2022-10-06 19:32 ` [ruby-core:110219] " byroot (Jean Boussier)
2022-10-13 15:17 ` [ruby-core:110276] " parker (Parker Finch)
2022-10-13 15:23 ` [ruby-core:110277] " chrisseaton (Chris Seaton)
2022-10-13 16:38 ` [ruby-core:110279] " tenderlovemaking (Aaron Patterson)
2022-10-14 20:04 ` parker (Parker Finch) [this message]
2022-10-17 17:31 ` [ruby-core:110369] " tenderlovemaking (Aaron Patterson)
2022-10-18 21:33 ` [ruby-core:110410] " parker (Parker Finch)
2023-02-17 14:42 ` [ruby-core:112476] " parker (Parker Finch) via ruby-core

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-99577.20221014200421.15511@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    --cc=ruby-core@neon.ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).