aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.mk1
-rw-r--r--internal/missing.h1
-rw-r--r--missing/setproctitle.c42
-rw-r--r--vm.c5
4 files changed, 45 insertions, 4 deletions
diff --git a/common.mk b/common.mk
index c650c6ab7f..171c7dfd30 100644
--- a/common.mk
+++ b/common.mk
@@ -19320,6 +19320,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm.$(OBJEXT): $(top_srcdir)/internal/inits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/missing.h
vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h
vm.$(OBJEXT): $(top_srcdir)/internal/object.h
vm.$(OBJEXT): $(top_srcdir)/internal/parse.h
diff --git a/internal/missing.h b/internal/missing.h
index c0992a151a..6ca508c8f9 100644
--- a/internal/missing.h
+++ b/internal/missing.h
@@ -13,6 +13,7 @@
/* missing/setproctitle.c */
#ifndef HAVE_SETPROCTITLE
extern void ruby_init_setproctitle(int argc, char *argv[]);
+extern void ruby_free_proctitle(void);
#endif
#endif /* INTERNAL_MISSING_H */
diff --git a/missing/setproctitle.c b/missing/setproctitle.c
index 6a85323818..d718123802 100644
--- a/missing/setproctitle.c
+++ b/missing/setproctitle.c
@@ -80,10 +80,20 @@ static char **argv1_addr = NULL;
#endif /* HAVE_SETPROCTITLE */
+#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
+# define ALLOCATE_ENVIRON 1
+#else
+# define ALLOCATE_ENVIRON 0
+#endif
+
+#if ALLOCATE_ENVIRON
+static char **orig_environ = NULL;
+#endif
+
void
compat_init_setproctitle(int argc, char *argv[])
{
-#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
+#if ALLOCATE_ENVIRON
extern char **environ;
char *lastargv = NULL;
char *lastenvp = NULL;
@@ -100,9 +110,10 @@ compat_init_setproctitle(int argc, char *argv[])
return;
/* Fail if we can't allocate room for the new environment */
- for (i = 0; envp[i] != NULL; i++)
- ;
- if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
+ for (i = 0; envp[i] != NULL; i++);
+
+ orig_environ = environ = xcalloc(i + 1, sizeof(*environ));
+ if (environ == NULL) {
environ = envp; /* put it back */
return;
}
@@ -134,6 +145,29 @@ compat_init_setproctitle(int argc, char *argv[])
#endif /* SPT_REUSEARGV */
}
+void
+ruby_free_proctitle(void)
+{
+#if ALLOCATE_ENVIRON
+ extern char **environ;
+
+ if (!orig_environ) return; /* environ is allocated by OS */
+
+ for (int i = 0; environ[i] != NULL; i++) {
+ xfree(environ[i]);
+ }
+
+ /* ruby_setenv could allocate a new environ, so we need to free both environ
+ * orig_environ in that case. */
+ if (environ != orig_environ) {
+ xfree(orig_environ);
+ orig_environ = NULL;
+ }
+
+ xfree(environ);
+#endif
+}
+
#ifndef HAVE_SETPROCTITLE
void
diff --git a/vm.c b/vm.c
index 257c517b43..37d631116a 100644
--- a/vm.c
+++ b/vm.c
@@ -20,6 +20,7 @@
#include "internal/eval.h"
#include "internal/gc.h"
#include "internal/inits.h"
+#include "internal/missing.h"
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/re.h"
@@ -3034,6 +3035,10 @@ ruby_vm_destruct(rb_vm_t *vm)
xfree(th->nt);
th->nt = NULL;
}
+
+#ifndef HAVE_SETPROCTITLE
+ ruby_free_proctitle();
+#endif
}
else {
if (th) {