Free environ when RUBY_FREE_AT_EXIT

The environ is malloc'd, so it gets reported as a memory leak. This
commit adds ruby_free_proctitle which frees it during shutdown when
RUBY_FREE_AT_EXIT is set.

    STACK OF 1 INSTANCE OF 'ROOT LEAK: <calloc in ruby_init_setproctitle>':
    5   dyld                                  0x18b7090e0 start + 2360
    4   ruby                                  0x10000e3a8 main + 100  main.c:58
    3   ruby                                  0x1000b4dfc ruby_options + 180  eval.c:121
    2   ruby                                  0x1001c5f70 ruby_process_options + 200  ruby.c:3014
    1   ruby                                  0x10035c9fc ruby_init_setproctitle + 76  setproctitle.c:105
    0   libsystem_malloc.dylib                0x18b8c7b78 _malloc_zone_calloc_instrumented_or_legacy + 100
This commit is contained in:
Peter Zhu 2024-01-09 13:17:17 -05:00
Родитель 4e0c2f05ef
Коммит 057df4379f
4 изменённых файлов: 45 добавлений и 4 удалений

Просмотреть файл

@ -19320,6 +19320,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm.$(OBJEXT): $(top_srcdir)/internal/hash.h vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm.$(OBJEXT): $(top_srcdir)/internal/inits.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/numeric.h
vm.$(OBJEXT): $(top_srcdir)/internal/object.h vm.$(OBJEXT): $(top_srcdir)/internal/object.h
vm.$(OBJEXT): $(top_srcdir)/internal/parse.h vm.$(OBJEXT): $(top_srcdir)/internal/parse.h

Просмотреть файл

@ -13,6 +13,7 @@
/* missing/setproctitle.c */ /* missing/setproctitle.c */
#ifndef HAVE_SETPROCTITLE #ifndef HAVE_SETPROCTITLE
extern void ruby_init_setproctitle(int argc, char *argv[]); extern void ruby_init_setproctitle(int argc, char *argv[]);
extern void ruby_free_proctitle(void);
#endif #endif
#endif /* INTERNAL_MISSING_H */ #endif /* INTERNAL_MISSING_H */

Просмотреть файл

@ -80,10 +80,20 @@ static char **argv1_addr = NULL;
#endif /* HAVE_SETPROCTITLE */ #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 void
compat_init_setproctitle(int argc, char *argv[]) compat_init_setproctitle(int argc, char *argv[])
{ {
#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV #if ALLOCATE_ENVIRON
extern char **environ; extern char **environ;
char *lastargv = NULL; char *lastargv = NULL;
char *lastenvp = NULL; char *lastenvp = NULL;
@ -100,9 +110,10 @@ compat_init_setproctitle(int argc, char *argv[])
return; return;
/* Fail if we can't allocate room for the new environment */ /* Fail if we can't allocate room for the new environment */
for (i = 0; envp[i] != NULL; i++) for (i = 0; envp[i] != NULL; i++);
;
if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) { orig_environ = environ = xcalloc(i + 1, sizeof(*environ));
if (environ == NULL) {
environ = envp; /* put it back */ environ = envp; /* put it back */
return; return;
} }
@ -134,6 +145,29 @@ compat_init_setproctitle(int argc, char *argv[])
#endif /* SPT_REUSEARGV */ #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 #ifndef HAVE_SETPROCTITLE
void void

5
vm.c
Просмотреть файл

@ -20,6 +20,7 @@
#include "internal/eval.h" #include "internal/eval.h"
#include "internal/gc.h" #include "internal/gc.h"
#include "internal/inits.h" #include "internal/inits.h"
#include "internal/missing.h"
#include "internal/object.h" #include "internal/object.h"
#include "internal/proc.h" #include "internal/proc.h"
#include "internal/re.h" #include "internal/re.h"
@ -3034,6 +3035,10 @@ ruby_vm_destruct(rb_vm_t *vm)
xfree(th->nt); xfree(th->nt);
th->nt = NULL; th->nt = NULL;
} }
#ifndef HAVE_SETPROCTITLE
ruby_free_proctitle();
#endif
} }
else { else {
if (th) { if (th) {