On Wed, 18 May 2005 04:42:47 +0900, nobu.nokada wrote:

> Hi,
> 
> At Wed, 18 May 2005 03:30:31 +0900,
> Jonathan Paisley wrote in [ruby-talk:142938]:
>> > Is this function called at each time when .so is loaded, and
>> > the area pointed by _NSGetArgv() shouldn't be changed?
>> > 
>> > I suspect that system dependent initialization of arguments
>> > should be integrated.
>> 
>> The _NSGetArgv function would appear to be an private function (inferring 
>> this from the leading underscore), so perhaps it'd be inappropriate to 
>> use it in the ruby core. Having said that, it is declared in <crt_externs.h>...
>> 
>> Perhaps an alternative would be to modify set_arg0() to change the
>> non-first argument to be empty C strings ("") rather than NULL?
> 
> "-AppleLanguages" can be disappeared?

I'm not entirely sure what you mean here. The CFRuntime code removes -AppleLanguages 
arguments from the command line, but the code that does it crashes if there are
NULLs present. We see the error if a ruby script calls set_arg0 before this happens.
set_arg0 sets argv[0], and sets argv[1 to argc-1] to NULL.

One of my suggestions was: in set_arg0 use empty strings ("") instead
of NULL values in set_arg0. This would prevent the crash.

An alternative would be just to link ruby with the CoreFoundation framework. That way,
the CFRuntime initialisation code should get executed before ruby initialises, and
the problem goes away.


> What about this?
> 
> void
> ruby_sysinit(argc, argv)
>     int *argc;
>     char ***argv;
> {
> #if defined(__APPLE__) && (defined(__MACH__) || defined(__DARWIN__))
>     int i, n = *argc, len = 0;
>     char **v1 = *argv, **v2 = ALLOC_N(char*, n + 1);
>     MEMCPY(v2, v1, char*, n);
>     v2[n] = 0;
>     for (i = 0; i < n; ++i) {
> 	v1[i] = strdup(v1[i]);
>     }
>     *argv = v2;
> #elif defined(__MACOS__) && defined(__MWERKS__)
>     *argc = ccommand(argv);
> #endif
> }

The problem with this is that it causes set_arg0 to not have the desired effect.

set_arg0 is designed to change the process name, as it appears in 'ps' output. 
To do this, it's necessary to overwrite the existing argument strings.
Note: what I mean here is overwriting the character data in the existing
strings, and not changing string pointers in the argv array. 'ps' (or in
kernel process info, depending on OS) reads directly from the argument
strings, not going through any pointers in an argv array.

The upshot is that changing argv for ruby in the proposed ruby_sysinit
means that a later set_arg0 will not change the necessary kernel-known
arguments. 

I still feel the solution is either to use empty strings rather than NULL
for filling the remaining argv pointers in set_arg0, or link ruby on OSX
to CoreFoundation by default. (I haven't tested whether the latter solves
the problem at hand - it should though).

Please let me know if I'm not making sense! :)

Thanks
Jonathan