diff options
Diffstat (limited to 'missing/setproctitle.c')
| -rw-r--r-- | missing/setproctitle.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/missing/setproctitle.c b/missing/setproctitle.c index f90886671c..5b2dfa65ce 100644 --- a/missing/setproctitle.c +++ b/missing/setproctitle.c @@ -87,7 +87,30 @@ static char **argv1_addr = NULL; #endif #if ALLOCATE_ENVIRON +/* system_environ is the value of environ before we allocate a custom buffer. + * + * We use this to restore environ in ruby_free_proctitle. + */ +static char **system_environ = NULL; +/* orig_environ is the buffer we allocate for environ. + * + * We use this to free this buffer in ruby_free_proctitle. When we add new + * environment variables using setenv, the system may change environ to a + * different buffer and will not free the original buffer, so we need to hold + * onto this so we can free it in ruby_free_proctitle. + * + * We must not free any of the contents because it may change if the system + * updates existing environment variables. + */ static char **orig_environ = NULL; +/* alloc_environ is a copy of orig_environ. + * + * We use this to free all the original string copies that were in orig_environ. + * Since environ could be changed to point to strings allocated by the system + * if environment variables are updated, so we need this to point to the + * original strings. + */ +static char **alloc_environ = NULL; #endif void @@ -112,6 +135,9 @@ compat_init_setproctitle(int argc, char *argv[]) /* Fail if we can't allocate room for the new environment */ for (i = 0; envp[i] != NULL; i++); + system_environ = environ; + + alloc_environ = xcalloc(i + 1, sizeof(*environ)); orig_environ = environ = xcalloc(i + 1, sizeof(*environ)); if (environ == NULL) { environ = envp; /* put it back */ @@ -140,8 +166,8 @@ compat_init_setproctitle(int argc, char *argv[]) argv_env_len = lastenvp - argv[0]; for (i = 0; envp[i] != NULL; i++) - environ[i] = ruby_strdup(envp[i]); - environ[i] = NULL; + alloc_environ[i] = environ[i] = ruby_strdup(envp[i]); + alloc_environ[i] = environ[i] = NULL; #endif /* SPT_REUSEARGV */ } @@ -153,16 +179,13 @@ ruby_free_proctitle(void) if (!orig_environ) return; /* environ is allocated by OS */ - /* ruby_setenv could allocate a new environ, so we need to free orig_environ - * in that case. */ - if (environ != orig_environ) { - for (int i = 0; orig_environ[i] != NULL; i++) { - xfree(orig_environ[i]); - } - - xfree(orig_environ); - orig_environ = NULL; + for (int i = 0; alloc_environ[i] != NULL; i++) { + xfree(alloc_environ[i]); } + xfree(alloc_environ); + xfree(orig_environ); + + environ = system_environ; #endif } |
