We need to keep a pointer to the originally allocated environ because
adding more environment variables can cause it to be changed to something
else.
For example:
100.times do |i|
ENV["FOO#{i}"] = "1"
end
Causes Valgrind to report:
312 bytes in 1 blocks are definitely lost in loss record 9 of 13
at 0x484D444: calloc (vg_replace_malloc.c:1340)
by 0x1884F8: calloc1 (gc.c:1844)
by 0x1884F8: objspace_xcalloc (gc.c:12202)
by 0x1884F8: ruby_xcalloc_body (gc.c:12209)
by 0x4204DD: ruby_init_setproctitle (setproctitle.c:119)
by 0x27DDF4: ruby_process_options (ruby.c:3101)
by 0x160BD1: ruby_options (eval.c:117)
by 0x15B96E: rb_main (main.c:40)
by 0x15B96E: main (main.c:59)
The call to setenv replaces the string in the environ array, which causes
the original string to be reported as a memory leak.
This commit allocates another copy of environ called alloc_environ that
contains the strings allocated by ruby_init_setproctitle. Then in
ruby_free_proctitle it frees all the strings in alloc_environ.
For example:
ENV.each { |k, v| ENV[k] = v.dup }
Valgrind reports:
3,321 bytes in 39 blocks are definitely lost in loss record 3 of 3
at 0x484884F: malloc (vg_replace_malloc.c:393)
by 0x25CB5B: objspace_xmalloc0 (gc.c:11972)
by 0x40344E: ruby_strdup (util.c:540)
by 0x59C854: ruby_init_setproctitle (setproctitle.c:143)
by 0x38CC44: ruby_process_options (ruby.c:3101)
by 0x234DB1: ruby_options (eval.c:117)
by 0x15B92E: rb_main (main.c:40)
by 0x15B92E: main (main.c:59)
It is undefined behaviour to free environ as it is managed by the system.
This caused RUBY_FREE_AT_EXIT to double free on systems like Linux. This
commit changes it to only free orig_environ, which is enough to make
both Valgrind and macOS leaks tools to not detect memory leaks.
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
when the RUBY_FREE_ON_SHUTDOWN environment variable is set, manually free memory at shutdown.
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
Co-authored-by: Peter Zhu <peter@peterzhu.ca>
If fmt is NULL, ptitle is uninitialized and used.
SETPROCTITLE(3bsd) says "If fmt is NULL, the process title is restored",
but looks like the feature is not implemented in missing/setproctitle.c.
At least the source code of ruby does not pass NULL to the function.
So I assume this function requires non-NULL fmt.
This issue was found by Coverity Scan.
for darwin (this header is missing in the iOS SDK)
* eval_intern.h: check HAVE_CRT_EXTERNS_H before including crt_externs.h, if
not defined, include missing/crt_externs.h instead
* hash.c: ditto
* missing/setproctitle.c: ditto
* missing/crt_externs.h: declare _NSGetEnviron() function and define environ
for iOS
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38644 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* missing/setproctitle.c (environ): use (*_NSGetEnviron()) instead of
environ on Darwin for namespace cleanness, same as [ruby-core:00537].
[ruby-core:45615] [Bug #6576]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36151 b2dd03c8-39d4-4d8f-98ff-823fe69b080e