Skip to content

Conversation

@ggmichaelgo
Copy link
Contributor

@ggmichaelgo ggmichaelgo commented Nov 12, 2025

Types of Changes

  • Bug fix.

PR Summary

When Memory::Sampler iterates String objects from the ObjectSpace, it truncates String to reduce memory usage and caches the results.

During this process, it is possible for the String objects to be internally locked. (Ruby String#rb_str_locktmp)

For example, when Socket#read is called, Ruby creates a buffer string that is temporarily locked. (Ruby Socket#rsock_s_recvfrom)
If the Memory::Sampler creates a report when the Socket#read is processing, it will raise a RuntimeError: can't modify string; temporarily locked error:

module Memory
  class Cache
    ...
    def lookup_string(obj)
      # since obj is internally locked, it can't be used as a Hash key
      @string_cache[obj] ||= String.new << obj[0, 64]
    end
  end
end

Contribution

@ggmichaelgo ggmichaelgo marked this pull request as ready for review November 12, 2025 21:02
@samuel-williams-shopify
Copy link
Contributor

This looks good to me. We can probably make a simpler / faster / more reliable test case by using the following behaviour:

fiber = Fiber.new do |string|
	IO::Buffer.for(string) do
		# string is now locked for the duration of this block.
		Fiber.yield
	end
end

# Lock the string
key = "foo"
fiber.resume(key)
{key => "bar"} # can't modify string; temporarily locked (RuntimeError)

@ioquatix ioquatix force-pushed the memory-safe-sampler branch from ecc2a3e to 6c854ee Compare November 17, 2025 03:08
@ioquatix ioquatix merged commit b1c5ad5 into socketry:main Nov 17, 2025
16 of 20 checks passed
@ioquatix ioquatix added this to the v0.12.0 milestone Nov 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants