ruby / ruby/rubygems

`with_env` is not thread safe.

Open
#8,000 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
4k
Forks
1.9k
Avg merge
1d 2h
Merged PRs (30d)
81

Description

The way with_env works is not thread safe, as it modifies the process global ENV. In addition, modifying ENV is extremely risky and can in practice lead to crashes and other issues, e.g. see https://www.evanjones.ca/setenv-is-not-thread-safe.html for more background.

https://github.com/rubygems/rubygems/blob/62c6aaf108cbf4c4070dab54769602e7ddc0d9fe/bundler/lib/bundler.rb#L699-L705

I also found that in practice, unbundled_env was difficult to use correctly, e.g.

env = Bundler.unbundled_env
Process.spawn(env, ...) # does not work as you might imagine

The reason is, env is:

Optional leading argument env is a hash of name/value pairs, where each name is a string and each value is a string or nil; each name/value pair is added to ENV in the new process. ... The effect is usually similar to that of calling ENV#update with argument env, where each named environment variable is created or updated (if the value is non-nil), or deleted (if the value is nil).

A better implementation would leave the values in place, with the value of nil, e.g.

env = ENV.to_h do |key, value|
  if key.start_with?('BUNDLE_')
    [key, nil]
  else
    [key, value]
  end
end

When env is used, the BUNDLE_ variables all have nil values, and will be automatically deleted from the child environment, while not affecting the parent environment.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in bundler/lib/bundler.rb around the referenced with_env implementation, then trace unbundled_env and how its result is passed to Process.spawn. Confirm the current process ENV is not modified and that BUNDLE_ entries are represented with nil values for the child environment, using the existing Bundler tests if found nearby.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.