From: "H.Yamamoto" Date: 2006-01-25T13:39:20+09:00 Subject: [ruby-dev:28281] Re: [PATCH] solaris 10 isinf and ruby_setenv fixes 山本です。 >もう今日はやらないつもりでしたが、思いついたことがあったので試して >みたところ、かなり単純化できました。 > > p ENV > $0 = $0 # test/unit/ui/console/testrunner.rb (HEAD) modifies $0 > p ENV > >パッチを当てると、HEAD も ruby_1_8 も二番目の p ENV が { , , , , } になります。 > >ruby_1_8 でエラーにならなかったのは、test/unit/ui/console/testrunner.rb で >$0 を変更していなかったからでした。 > >そして $0= の実装である set_arg0 には > > ruby_setenv("", NULL); /* duplicate environ vars */ > >なんて行があるので、どうも setenv の独自実装と $0= は依存している感じですね。 $0= で origargv を変更しているのが environ にも影響している感じなのですが、 この処理って本当に必要なんでしょうか?environ を変更するのと同じぐらい 危ない処理に思えますが・・・ マニュアルによると、$0= を使うと ps の結果が変わることがあるという説明なので、 変わらなくなっても仕様に反することにはならないかなと思うのですが・・・ とりあえず、下のパッチで TestDrive でも成功するようになりました。 まとめると、 1. set_arg0 は environ がコピーされることを前提とする場合がある(setproctitle(3) がない場合など) 2. にもかかわらず ruby_setenv で独自実装を使わず setenv(3) を使うと、set_arg0 を 呼んだときに一緒に environ まで変更されてしまうことがある。 3. しかし、environ を直接変更するのは規約に違反し、Solaris では SEGV するらしい。 Index: configure.in =================================================================== RCS file: /src/ruby/configure.in,v retrieving revision 1.296 diff -u -w -b -p -r1.296 configure.in --- configure.in 22 Jan 2006 11:34:51 -0000 1.296 +++ configure.in 24 Jan 2006 01:45:39 -0000 @@ -506,7 +506,7 @@ AC_CHECK_FUNCS(fmod killpg wait4 waitpid getpriority getrlimit setrlimit\ dlopen sigprocmask sigaction _setjmp vsnprintf snprintf\ setsid telldir seekdir fchmod mktime timegm cosh sinh tanh\ - setuid setgid daemon select_large_fdset) + setuid setgid daemon select_large_fdset unsetenv) AC_ARG_ENABLE(setreuid, [ --enable-setreuid use setreuid()/setregid() according to need even if obsolete.], [use_setreuid=$enableval]) @@ -514,6 +514,20 @@ if test "$use_setreuid" = yes; then AC_DEFINE(USE_SETREUID) AC_DEFINE(USE_SETREGID) fi +AC_CACHE_CHECK(for setenv (2 arguments), rb_cv_have_setenv_2args, + [AC_TRY_COMPILE([#include ], [setenv("foo", "foo");], + rb_cv_have_setenv_2args=yes, + rb_cv_have_setenv_2args=no)]) +if test "$rb_cv_have_setenv_2args" = yes; then + AC_DEFINE(HAVE_SETENV_2ARGS) +fi +AC_CACHE_CHECK(for setenv (3 arguments), rb_cv_have_setenv_3args, + [AC_TRY_COMPILE([#include ], [setenv("foo", "foo", 1);], + rb_cv_have_setenv_3args=yes, + rb_cv_have_setenv_3args=no)]) +if test "$rb_cv_have_setenv_3args" = yes; then + AC_DEFINE(HAVE_SETENV_3ARGS) +fi AC_STRUCT_TIMEZONE AC_CACHE_CHECK(for struct tm.tm_gmtoff, rb_cv_member_struct_tm_tm_gmtoff, [AC_TRY_COMPILE([#include ], Index: hash.c =================================================================== RCS file: /src/ruby/hash.c,v retrieving revision 1.159 diff -u -w -b -p -r1.159 hash.c --- hash.c 20 Oct 2005 02:56:22 -0000 1.159 +++ hash.c 24 Jan 2006 10:03:23 -0000 @@ -1690,7 +1690,14 @@ ruby_setenv(const char *name, const char * RTL's environ global variable directly yet. */ SetEnvironmentVariable(name,value); -#elif defined __CYGWIN__ +#elif defined(HAVE_SETENV_2ARGS) && defined(HAVE_UNSETENV) +#undef setenv +#undef unsetenv + if (value) + setenv(name,value); + else + unsetenv(name); +#elif defined(HAVE_SETENV_3ARGS) && defined(HAVE_UNSETENV) #undef setenv #undef unsetenv if (value) Index: ruby.c =================================================================== RCS file: /src/ruby/ruby.c,v retrieving revision 1.112 diff -u -w -b -p -r1.112 ruby.c --- ruby.c 12 Dec 2005 00:35:08 -0000 1.112 +++ ruby.c 24 Jan 2006 11:25:49 -0000 @@ -1041,51 +1041,10 @@ set_arg0(VALUE val, ID id) j.pst_command = s; pstat(PSTAT_SETCMD, j, i, 0, 0); } - rb_progname = rb_tainted_str_new(s, i); #elif defined(HAVE_SETPROCTITLE) setproctitle("%.*s", (int)i, s); - rb_progname = rb_tainted_str_new(s, i); -#else - if (len == 0) { - char *s = origargv[0]; - int i; - - s += strlen(s); - /* See if all the arguments are contiguous in memory */ - for (i = 1; i < origargc; i++) { - if (origargv[i] == s + 1) { - s++; - s += strlen(s); /* this one is ok too */ - } - else { - break; - } - } -#ifndef DOSISH - if (s + 1 == envspace.begin) { - s = envspace.end; - ruby_setenv("", NULL); /* duplicate environ vars */ - } -#endif - len = s - origargv[0]; - } - - if (i >= len) { - i = len; - memcpy(origargv[0], s, i); - origargv[0][i] = '\0'; - } - else { - memcpy(origargv[0], s, i); - s = origargv[0]+i; - *s++ = '\0'; - while (++i < len) - *s++ = ' '; - for (i = 1; i < origargc; i++) - origargv[i] = 0; - } - rb_progname = rb_tainted_str_new2(origargv[0]); #endif + rb_progname = rb_tainted_str_new(s, i); } void