summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorRohit Menon <rohitmenon@verizon.net>2021-07-01 20:04:52 -0400
committerKoichi Sasada <ko1@atdot.net>2021-12-15 15:04:34 +0900
commitd3d156c21ecf0a602d366209b3e2da665c3ec389 (patch)
tree6cfb80f875ccbf95c89e13fdfb0993c70d601edd /hash.c
parent0fcc58a18c7c8896df1736fc644c1c9f84a6df0f (diff)
downloadruby-d3d156c21ecf0a602d366209b3e2da665c3ec389.tar.gz
Add locks for ENV
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c229
1 files changed, 183 insertions, 46 deletions
diff --git a/hash.c b/hash.c
index 270ddfb522..e58d21587d 100644
--- a/hash.c
+++ b/hash.c
@@ -43,6 +43,7 @@
#include "ruby_assert.h"
#include "symbol.h"
#include "transient_heap.h"
+#include "ruby/thread_native.h"
#ifndef HASH_DEBUG
#define HASH_DEBUG 0
@@ -4808,6 +4809,17 @@ extern char **environ;
#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
#endif
+rb_nativethread_lock_t env_lock;
+
+const char*
+getenv_with_lock(const char *name)
+{
+ rb_native_mutex_lock(&env_lock);
+ char *result = getenv(name);
+ rb_native_mutex_unlock(&env_lock);
+ return result;
+}
+
static inline rb_encoding *
env_encoding(void)
{
@@ -4906,7 +4918,7 @@ static VALUE
env_delete(VALUE name)
{
const char *nam = env_name(name);
- const char *val = getenv(nam);
+ const char *val = getenv_with_lock(nam);
reset_by_modified_env(nam);
@@ -4972,7 +4984,7 @@ rb_f_getenv(VALUE obj, VALUE name)
const char *nam, *env;
nam = env_name(name);
- env = getenv(nam);
+ env = getenv_with_lock(nam);
if (env) {
return env_name_new(nam, env);
}
@@ -5018,7 +5030,7 @@ env_fetch(int argc, VALUE *argv, VALUE _)
rb_warn("block supersedes default value argument");
}
nam = env_name(key);
- env = getenv(nam);
+ env = getenv_with_lock(nam);
if (!env) {
if (block_given) return rb_yield(key);
if (argc == 1) {
@@ -5054,12 +5066,14 @@ envix(const char *nam)
register int i, len = strlen(nam);
char **env;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
for (i = 0; env[i]; i++) {
if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
break; /* memcmp must come first to avoid */
} /* potential SEGV's */
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return i;
}
#endif
@@ -5160,11 +5174,13 @@ ruby_setenv(const char *name, const char *value)
wname[len-1] = L'=';
#endif
}
+ rb_native_mutex_lock(&env_lock);
#ifndef HAVE__WPUTENV_S
failed = _wputenv(wname);
#else
failed = _wputenv_s(wname, wvalue);
#endif
+ rb_native_mutex_unlock(&env_lock);
ALLOCV_END(buf);
/* even if putenv() failed, clean up and try to delete the
* variable from the system area. */
@@ -5178,6 +5194,7 @@ ruby_setenv(const char *name, const char *value)
invalid_envname(name);
}
#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
+ rb_native_mutex_lock(&env_lock);
if (value) {
if (setenv(name, value, 1))
rb_sys_fail_str(rb_sprintf("setenv(%s)", name));
@@ -5190,11 +5207,13 @@ ruby_setenv(const char *name, const char *value)
rb_sys_fail_str(rb_sprintf("unsetenv(%s)", name));
#endif
}
+ rb_native_mutex_unlock(&env_lock);
#elif defined __sun
/* Solaris 9 (or earlier) does not have setenv(3C) and unsetenv(3C). */
/* The below code was tested on Solaris 10 by:
% ./configure ac_cv_func_setenv=no ac_cv_func_unsetenv=no
*/
+ rb_native_mutex_lock(&env_lock);
size_t len, mem_size;
char **env_ptr, *str, *mem_ptr;
@@ -5220,6 +5239,7 @@ ruby_setenv(const char *name, const char *value)
rb_sys_fail_str(rb_sprintf("putenv(%s)", name));
}
}
+ rb_native_mutex_unlock(&env_lock);
#else /* WIN32 */
size_t len;
int i;
@@ -5347,18 +5367,31 @@ env_keys(int raw)
rb_encoding *enc = raw ? 0 : rb_locale_encoding();
ary = rb_ary_new();
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while(*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s) {
- const char *p = *env;
size_t l = s - p;
VALUE e = raw ? rb_utf8_str_new(p, l) : env_enc_str_new(p, l, enc);
rb_ary_push(ary, e);
}
- env++;
}
- FREE_ENVIRON(environ);
return ary;
}
@@ -5387,6 +5420,7 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
char **env;
long cnt = 0;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
for (; *env ; ++env) {
if (strchr(*env, '=')) {
@@ -5394,6 +5428,7 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
}
}
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return LONG2FIX(cnt);
}
@@ -5435,15 +5470,29 @@ env_values(void)
char **env;
ary = rb_ary_new();
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s) {
rb_ary_push(ary, env_str_new2(s+1));
}
- env++;
}
- FREE_ENVIRON(environ);
return ary;
}
@@ -5524,16 +5573,30 @@ env_each_pair(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
ary = rb_ary_new();
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s) {
- rb_ary_push(ary, env_str_new(*env, s-*env));
+ rb_ary_push(ary, env_str_new(p, s-p));
rb_ary_push(ary, env_str_new2(s+1));
}
- env++;
}
- FREE_ENVIRON(environ);
if (rb_block_pair_yield_optimizable()) {
for (i=0; i<RARRAY_LEN(ary); i+=2) {
@@ -5877,23 +5940,37 @@ env_inspect(VALUE _)
VALUE str, i;
str = rb_str_buf_new2("{");
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
- if (env != environ) {
+ if (current_pair != 0) {
rb_str_buf_cat2(str, ", ");
}
if (s) {
rb_str_buf_cat2(str, "\"");
- rb_str_buf_cat(str, *env, s-*env);
+ rb_str_buf_cat(str, p, s-p);
rb_str_buf_cat2(str, "\"=>");
i = rb_inspect(rb_str_new2(s+1));
rb_str_buf_append(str, i);
}
- env++;
}
- FREE_ENVIRON(environ);
rb_str_buf_cat2(str, "}");
return str;
@@ -5915,16 +5992,30 @@ env_to_a(VALUE _)
VALUE ary;
ary = rb_ary_new();
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s) {
- rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env),
+ rb_ary_push(ary, rb_assoc_new(env_str_new(p, s-p),
env_str_new2(s+1)));
}
- env++;
}
- FREE_ENVIRON(environ);
return ary;
}
@@ -5958,10 +6049,12 @@ env_size(VALUE _)
int i;
char **env;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
for (i=0; env[i]; i++)
;
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return INT2FIX(i);
}
@@ -5980,12 +6073,15 @@ env_empty_p(VALUE _)
{
char **env;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
if (env[0] == 0) {
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return Qtrue;
}
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return Qfalse;
}
@@ -6020,7 +6116,7 @@ env_has_key(VALUE env, VALUE key)
const char *s;
s = env_name(key);
- return RBOOL(getenv(s));
+ return RBOOL(getenv_with_lock(s));
}
/*
@@ -6049,7 +6145,7 @@ env_assoc(VALUE env, VALUE key)
const char *s, *e;
s = env_name(key);
- e = getenv(s);
+ e = getenv_with_lock(s);
if (e) return rb_assoc_new(key, env_str_new2(e));
return Qnil;
}
@@ -6073,6 +6169,7 @@ env_has_value(VALUE dmy, VALUE obj)
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
@@ -6080,12 +6177,14 @@ env_has_value(VALUE dmy, VALUE obj)
long len = strlen(s);
if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return Qtrue;
}
}
env++;
}
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return Qfalse;
}
@@ -6110,20 +6209,24 @@ env_rassoc(VALUE dmy, VALUE obj)
obj = rb_check_string_type(obj);
if (NIL_P(obj)) return Qnil;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
while (*env) {
- char *s = strchr(*env, '=');
+ const char *p = *env;
+ char *s = strchr(p, '=');
if (s++) {
long len = strlen(s);
if (RSTRING_LEN(obj) == len && strncmp(s, RSTRING_PTR(obj), len) == 0) {
- VALUE result = rb_assoc_new(rb_str_new(*env, s-*env-1), obj);
- FREE_ENVIRON(environ);
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ VALUE result = rb_assoc_new(rb_str_new(p, s-p-1), obj);
return result;
}
}
env++;
}
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return Qnil;
}
@@ -6150,20 +6253,34 @@ env_key(VALUE dmy, VALUE value)
VALUE str;
SafeStringValue(value);
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s++) {
long len = strlen(s);
if (RSTRING_LEN(value) == len && strncmp(s, RSTRING_PTR(value), len) == 0) {
- str = env_str_new(*env, s-*env-1);
- FREE_ENVIRON(environ);
+ str = env_str_new(p, s-p-1);
return str;
}
}
env++;
}
- FREE_ENVIRON(environ);
return Qnil;
}
@@ -6174,16 +6291,30 @@ env_to_hash(void)
VALUE hash;
hash = rb_hash_new();
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
- while (*env) {
- char *s = strchr(*env, '=');
+ int pair_count = 0;
+ while (*(env+pair_count)) {
+ pair_count++;
+ }
+ VALUE env_pairs[pair_count];
+ for(int i = 0; i < pair_count; i++)
+ {
+ const char *p = *env;
+ env_pairs[i] = p;
+ env++;
+ }
+ FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
+ for(int current_pair = 0; current_pair < pair_count; current_pair++)
+ {
+ const char *p = env_pairs[current_pair];
+ char *s = strchr(p, '=');
if (s) {
- rb_hash_aset(hash, env_str_new(*env, s-*env),
+ rb_hash_aset(hash, env_str_new(p, s-p),
env_str_new2(s+1));
}
- env++;
}
- FREE_ENVIRON(environ);
return hash;
}
@@ -6322,17 +6453,23 @@ env_shift(VALUE _)
char **env;
VALUE result = Qnil;
+ rb_native_mutex_lock(&env_lock);
env = GET_ENVIRON(environ);
if (*env) {
- char *s = strchr(*env, '=');
+ const char *p = *env;
+ rb_native_mutex_unlock(&env_lock);
+ char *s = strchr(p, '=');
if (s) {
- VALUE key = env_str_new(*env, s-*env);
- VALUE val = env_str_new2(getenv(RSTRING_PTR(key)));
+ VALUE key = env_str_new(p, s-p);
+ VALUE val = env_str_new2(getenv_with_lock(RSTRING_PTR(key)));
env_delete(key);
result = rb_assoc_new(key, val);
}
+ rb_native_mutex_lock(&env_lock);
}
+
FREE_ENVIRON(environ);
+ rb_native_mutex_unlock(&env_lock);
return result;
}