Process.spawn is supposed to unset environment variables that are explicitly specified as nil. Instead, the environment variable is being set as "". This happens even if the environment variable didn't exist before calling Process.spawn.
Below is a sample script demonstrating the problem:
I just ran across this today. @smellsblue are you still interested in submitting a fix?
The importance of this issue is compounded by the fact that Process.spawn on JRuby doesn't support the :unsetenv_others option (we get: "clearing env in child is not supported"). So there's no way of removing an environment variable which is already set directly from Process.spawn (or any method that relies on it).
The workaround is to manipulate the ENV variable directly, though that impacts the parent process too.
@smellsblue We'd love the help! The link I show down below in the discussion of :unsetenv_others is right in the heart of the logic, roughly "ported" from the way MRI handles the various spawn forms. This may be a simple oversight, where we should be scrubbing the env of any of these variables specified as nil. It may be something that was fixed later in CRuby, too...I did the original work on this code a couple years ago.
Relating to unsetenv, which is likely intertwined with this logic...
The logic here is largely modeled after what's in MRI, drastically modified in most places to accommodate the limitations of posix_spawn, which we use to mostly simulate fork+exec.
I did not translate any of the logic from MRI's unsetenv_others logic, and left this comment for future generations to ponder over:
// only way to do this is manually build a list of env assignments that clear all parent values
Let us wonder at the mystery.
I believe what I was saying here is that because posix_spawn only has a way to specify a full environment, the JRuby version of this logic would need to duplicate the existing env and dig out the ones that are to be cleared.
In CRuby, they do this "the easy way" by forking, altering the environment, and then execing the new process which inherits this in-place modified environment. We can't modify the in-place environment without introducing some nasty side effects for the parent JVM, so the alternative is to manually construct a completely new env and pass that to posix_spawn. At the time, that was not a critical path item for us.
And largely, I've just missed this issue. This subsystem is one of my unfortunate creations, and there's plenty of holes where I lost the tune.