@@ -13,6 +13,31 @@ require "crystal/system/env"
1313#
1414# NOTE: All keys and values are strings. You must take care to cast other types
1515# at runtime, e.g. integer port numbers.
16+ #
17+ # ### Safety
18+ #
19+ # Modifying the environment in single-threaded programs is safe. Modifying the
20+ # environment is also always safe on Windows.
21+ #
22+ # Modifying the environment in multi-threaded programs on other targets is
23+ # always unsafe, and can cause a mere read to segfault! At best, memory will be
24+ # leaked every time the environment is modified.
25+ #
26+ # The problem is that POSIX systems don't guarantee a thread safe implementation
27+ # of the `getenv`, `setenv` and `putenv` libc functions. Any thread that gets an
28+ # environment variable while another thread sets an environment variable may
29+ # segfault. The `ENV` object itself is internally protected by a readers-writer
30+ # lock, but we can't protect against external libraries, including libc calls
31+ # made by the stdlib. They might call `getenv` internally without holding the
32+ # read lock while a crystal fiber with the write lock calls `setenv`.
33+ #
34+ # The only safe solution is to consider `ENV` to be immutable, and to never call
35+ # `ENV.[]=`, `ENV.delete` or `ENV.clear` in your program. If you really need to,
36+ # you must make sure that no other thread has been started (beware of libraries
37+ # that may start threads).
38+ #
39+ # NOTE: Passing environment variables to a child process should use the `env`
40+ # arg of `Process.run` and `Process.new`.
1641module ENV
1742 extend Enumerable ({String , String })
1843
@@ -34,6 +59,9 @@ module ENV
3459 # If *value* is `nil`, the environment variable is deleted.
3560 #
3661 # If *key* or *value* contains a null-byte an `ArgumentError` is raised.
62+ #
63+ # WARNING: It is recommended to never set environment variables. See the
64+ # Safety section of `ENV` for details.
3765 def self. []= (key : String , value : String ?)
3866 Crystal ::System ::Env .set(key, value)
3967
@@ -90,6 +118,9 @@ module ENV
90118
91119 # Removes the environment variable named *key*. Returns the previous value if
92120 # the environment variable existed, otherwise returns `nil`.
121+ #
122+ # WARNING: It is recommended to never delete environment variables. See the
123+ # Safety section of `ENV` for details.
93124 def self.delete (key : String ) : String ?
94125 if value = self [key]?
95126 Crystal ::System ::Env .set(key, nil )
@@ -113,6 +144,8 @@ module ENV
113144 end
114145 end
115146
147+ # WARNING: It is recommended to never delete environment variables. See the
148+ # Safety section of `ENV` for details.
116149 def self.clear : Nil
117150 keys.each { |k | delete k }
118151 end
0 commit comments