I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
Bill
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
and later:
ADD_FUNCTION("putenv", f_system_putenv, tFunc(tStr, tInt), 0); ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)), 0);
test script:
int fail=0; int main() { string var="DISPLAY"; string val="BASE"; int a='A'; for(int i=0; i<2050; i++) { val+=String.int2char(a); werror("iteration " + i + "\n"); doit(var,val); } werror("failures: " + fail + "\n"); return 1; } void doit(string var, string val) { if(System.putenv(var+"="+ val)) werror("failed putenv\n"); string r=System.getenv(var); if(r!=val) { fail++; }
The test fails consistently and in the same locations for a given environment variable. The manpage doesn't say what might cause failures like this.
Any thoughts?
Bill
In the last episode (Oct 16), Bill Welliver said:
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
You'll want to strdup envvar before calling putenv. http://www.opengroup.org/onlinepubs/007904975/functions/putenv.html :
The putenv() function shall make the value of the environment variable name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment.
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
You'll probably want to call make_shared_string on rv before returning it, too. http://www.opengroup.org/onlinepubs/007904975/functions/getenv.html :
The string pointed to may be overwritten by a subsequent call to getenv(), setenv(), or unsetenv(), but shall not be overwritten by a call to any other function in this volume of IEEE Std 1003.1-2001. The getenv() function need not be reentrant. A function that is not required to be reentrant is not required to be thread-safe.
interesting. not mentioned in my man pages, either.
On Thu, 16 Oct 2003, Dan Nelson wrote:
In the last episode (Oct 16), Bill Welliver said:
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
You'll want to strdup envvar before calling putenv. http://www.opengroup.org/onlinepubs/007904975/functions/putenv.html :
The putenv() function shall make the value of the environment variable name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment.
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
You'll probably want to call make_shared_string on rv before returning it, too. http://www.opengroup.org/onlinepubs/007904975/functions/getenv.html :
The string pointed to may be overwritten by a subsequent call to getenv(), setenv(), or unsetenv(), but shall not be overwritten by a call to any other function in this volume of IEEE Std 1003.1-2001. The getenv() function need not be reentrant. A function that is not required to be reentrant is not required to be thread-safe.
-- Dan Nelson dnelson@allantgroup.com
In the last episode (Oct 16), Bill Welliver said:
interesting. not mentioned in my man pages, either.
The getenv() restrictions may not apply to your system; POSIX just has to list them in case you ever compile on a system where they _do_ apply :) The putenv() stuff always says "shall", so it seems to be dictating policy for all implementations there.
You'll want to strdup envvar before calling putenv.
I've strdup()ed the input to putenv and the output of getenv, but it seems to have made little difference.
You'll probably want to call make_shared_string on rv before returning it, too.
According to interpret.h, push_text includes a make_shared_string.
It's really odd, as it doesn't always fail, and it's not obvious that there's any pattern (not that that would make any difference). It does fail about 33 times over 2050 iterations of increasing length.
Example (showing only failures):
# /usr/local/bin/pike test.pike fail: put "BASEAAAA", got "BASEAAA" fail: put "BASEAAAAA", got "BASEAAA" fail: put "BASEAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAAAAAA", got "BASEAAA" fail: put "BASEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", got "BASEAAAAAAAAAAAAAAAA" fail: put "BASEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", got "BASEAAAAAAAAAAAAAAAAAAAAAAAA"
putenv(3) is a strange function that way; it's essentially impossible to write a pike wrapper for it without causing memory leaks. I guess that's why it doesn't exist already.
Bill, in your putenv glue I think you should note prominently in the doc that it will leak. You should also make a call to dmalloc_accept_leak with the strdup'ed string that leaks, so that dmalloc won't report them. Ideally _memory_usage should also return how much have leaked that way, so that users can check that.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-16 22:43: Subject: Re: putenv/getenv
In the last episode (Oct 16), Bill Welliver said:
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
You'll want to strdup envvar before calling putenv. http://www.opengroup.org/onlinepubs/007904975/functions/putenv.html :
The putenv() function shall make the value of the environment variable name equal to value by altering an existing variable or creating a new one. In either case, the string pointed to by string shall become part of the environment, so altering the string shall change the environment.
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
You'll probably want to call make_shared_string on rv before returning it, too. http://www.opengroup.org/onlinepubs/007904975/functions/getenv.html :
The string pointed to may be overwritten by a subsequent call to getenv(), setenv(), or unsetenv(), but shall not be overwritten by a call to any other function in this volume of IEEE Std 1003.1-2001. The getenv() function need not be reentrant. A function that is not required to be reentrant is not required to be thread-safe.
-- Dan Nelson dnelson@allantgroup.com
/ Brevbäraren
You could track the allocated strings and free them if the same environment variable is set to something else. Then the strings are never actually leaked.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-17 16:51: Subject: Re: putenv/getenv
putenv(3) is a strange function that way; it's essentially impossible to write a pike wrapper for it without causing memory leaks. I guess that's why it doesn't exist already.
Bill, in your putenv glue I think you should note prominently in the doc that it will leak. You should also make a call to dmalloc_accept_leak with the strdup'ed string that leaks, so that dmalloc won't report them. Ideally _memory_usage should also return how much have leaked that way, so that users can check that.
/ Martin Stjernholm, Roxen IS
That doesn't work if there is other C code that use putenv(3) directly. But it would still help bringing down the leaking quite a bit.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-17 16:53: Subject: Re: putenv/getenv
You could track the allocated strings and free them if the same environment variable is set to something else. Then the strings are never actually leaked.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
At least it puts a bound on the leak. There can be at most one string leaked per variable set.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-17 16:56: Subject: Re: putenv/getenv
That doesn't work if there is other C code that use putenv(3) directly. But it would still help bringing down the leaking quite a bit.
/ Martin Stjernholm, Roxen IS
OK, after making some of the recommended changes, the code now passes the test program. Guess that just leaves the problem of tracking allocations.
Does the system module remain between calls to member functions? Where would my allocation tracking be stored?
Bill
Do they need to be freed on subsequent putenv() calls on the same variable?
I guess the module space would be the right place for that; hopefully the system module wont be unloaded (it's not by any easy means).
/ Mirar
Previous text:
2003-10-17 18:52: Subject: Re: putenv/getenv
OK, after making some of the recommended changes, the code now passes the test program. Guess that just leaves the problem of tracking allocations.
Does the system module remain between calls to member functions? Where would my allocation tracking be stored?
Bill
/ Brevbäraren
ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)),
You don't need tOr(tStr, tInt) just because the function can return 0. 0 is a valid value for tStr, and every other type as well (except float (Hi Al! :) ).
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-16 21:06: Subject: putenv/getenv
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
Bill
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
and later:
ADD_FUNCTION("putenv", f_system_putenv, tFunc(tStr, tInt), 0); ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)), 0);
test script:
int fail=0; int main() { string var="DISPLAY"; string val="BASE"; int a='A'; for(int i=0; i<2050; i++) { val+=String.int2char(a); werror("iteration " + i + "\n"); doit(var,val); } werror("failures: " + fail + "\n"); return 1; } void doit(string var, string val) { if(System.putenv(var+"="+ val)) werror("failed putenv\n"); string r=System.getenv(var); if(r!=val) { fail++; }
The test fails consistently and in the same locations for a given environment variable. The manpage doesn't say what might cause failures like this.
Any thoughts?
Bill
/ Brevbäraren
Am I missing something?
Pike v7.5 release 12 running Hilfe v3.5 (Incremental Pike Frontend)
putenv("hello", "world");
(1) Result: 0
getenv("hello");
(2) Result: "world"
/ David Hedbor
Previous text:
2003-10-16 21:06: Subject: putenv/getenv
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
Bill
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
and later:
ADD_FUNCTION("putenv", f_system_putenv, tFunc(tStr, tInt), 0); ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)), 0);
test script:
int fail=0; int main() { string var="DISPLAY"; string val="BASE"; int a='A'; for(int i=0; i<2050; i++) { val+=String.int2char(a); werror("iteration " + i + "\n"); doit(var,val); } werror("failures: " + fail + "\n"); return 1; } void doit(string var, string val) { if(System.putenv(var+"="+ val)) werror("failed putenv\n"); string r=System.getenv(var); if(r!=val) { fail++; }
The test fails consistently and in the same locations for a given environment variable. The manpage doesn't say what might cause failures like this.
Any thoughts?
Bill
/ Brevbäraren
Yes. Those strings are stored in a mapping in the master, and thus not visible to C code. They are not actually stored in the environment area of the process.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-17 16:39: Subject: putenv/getenv
Am I missing something?
Pike v7.5 release 12 running Hilfe v3.5 (Incremental Pike Frontend)
putenv("hello", "world");
(1) Result: 0
getenv("hello");
(2) Result: "world"
/ David Hedbor
Ah, interesting. I had no idea that was the case.
/ David Hedbor
Previous text:
2003-10-17 16:41: Subject: putenv/getenv
Yes. Those strings are stored in a mapping in the master, and thus not visible to C code. They are not actually stored in the environment area of the process.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args);
This pop is too early - envvar might point to freed memory after it since it only points to the data block of the string without adding a reference to it.
I saw exactly this error in many places in the Caudium C module. Did you start from that code, or is there some other bad examples out there that people are copying?
rv=putenv(envvar);
Note that pike strings can contain NUL chars, so if you pass them directly to a libc function like this it might read a truncated string. Maybe you should check that the passed string doesn't contain NUL?
push_int(rv); }
Most functions of this type return 0 on failure and nonzero on success, so maybe you should invert the return value.
Or even better would be to declare putenv as returning void and throw an error instead, since the only possible error is ENOMEM, and pike generally throws errors when running out of memory.
Also, wouldn't it be nicer to let the function take the name and the value in separate strings, so that the user doesn't have to glue together one with "="? Then you could also check that the name doesn't contain "=" already.
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args);
Same thing here, of course.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-16 21:06: Subject: putenv/getenv
I've cobbled together a System.putenv() and System.getenv(), but I'm having some odd problems. The code itself works most of the time, but randomly getenv() fails to get an envvar I've putenv()ed (ie getenv(2) returns NULL). The functions are below, along with a short test script that demonstrates the problem. Any suggestions are welcome, as my C skills are quite rusty.
Bill
in modules/system/system.c:
#include <stdlib.h> static void f_system_putenv(INT32 args) { int rv; char *envvar; get_all_args("putenv", args, "%s", &envvar); pop_n_elems(args); rv=putenv(envvar); push_int(rv); }
static void f_system_getenv(INT32 args) { char *rv; char *envvar; get_all_args("getenv", args, "%s", &envvar); pop_n_elems(args); rv=getenv(envvar); if(rv==NULL) push_int(0); else push_text(rv); }
and later:
ADD_FUNCTION("putenv", f_system_putenv, tFunc(tStr, tInt), 0); ADD_FUNCTION("getenv", f_system_getenv, tFunc(tStr, tOr(tStr, tInt)), 0);
test script:
int fail=0; int main() { string var="DISPLAY"; string val="BASE"; int a='A'; for(int i=0; i<2050; i++) { val+=String.int2char(a); werror("iteration " + i + "\n"); doit(var,val); } werror("failures: " + fail + "\n"); return 1; } void doit(string var, string val) { if(System.putenv(var+"="+ val)) werror("failed putenv\n"); string r=System.getenv(var); if(r!=val) { fail++; }
The test fails consistently and in the same locations for a given environment variable. The manpage doesn't say what might cause failures like this.
Any thoughts?
Bill
/ Brevbäraren
On Fri, 17 Oct 2003, Martin Stjernholm, Roxen IS @ Pike developers forum wrote:
This pop is too early - envvar might point to freed memory after it since it only points to the data block of the string without adding a reference to it.
I saw exactly this error in many places in the Caudium C module. Did you start from that code, or is there some other bad examples out there that people are copying?
Actually, i wrote it from scratch based on looking at other functions in sytem.c. It makes sense to me that would be a problem. I assume then that it is more proper to wait until the latest possible moment before popping items from the stack, right?
Note that pike strings can contain NUL chars, so if you pass them directly to a libc function like this it might read a truncated string. Maybe you should check that the passed string doesn't contain NUL?
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Most functions of this type return 0 on failure and nonzero on success, so maybe you should invert the return value.
Or even better would be to declare putenv as returning void and throw an error instead, since the only possible error is ENOMEM, and pike generally throws errors when running out of memory.
Also, wouldn't it be nicer to let the function take the name and the value in separate strings, so that the user doesn't have to glue together one with "="? Then you could also check that the name doesn't contain "=" already.
Actually, I like the idea of throwing an error on failure. If I were able to get this to work properly, i was thinking about modifying the predef::putenv() to call the System.putenv() if it existed.
Bill
Actually, i wrote it from scratch based on looking at other functions in sytem.c.
Indeed there is a function f_get_netinfo_property in system.c that has this error. The others look correct.
/.../ I assume then that it is more proper to wait until the latest possible moment before popping items from the stack, right?
Well, rather to a late enough moment. They can be popped only when you stopped referring to them. If the latest possible moment is before that, you have to restructure your code to solve it.
Tip: The macro stack_pop_n_elems_keep_top should always make it possible to postpone it to just before the return.
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Yes, I think so too.
/.../ i was thinking about modifying the predef::putenv() to call the System.putenv() if it existed.
It'd be necessary to limit leaking according to Marcus' suggestion before you can do that, imo.
As for "if it existed" I believe it's neigh impossible to find a system where it doesn't.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-17 17:12: Subject: Re: putenv/getenv
On Fri, 17 Oct 2003, Martin Stjernholm, Roxen IS @ Pike developers forum wrote:
This pop is too early - envvar might point to freed memory after it since it only points to the data block of the string without adding a reference to it.
I saw exactly this error in many places in the Caudium C module. Did you start from that code, or is there some other bad examples out there that people are copying?
Actually, i wrote it from scratch based on looking at other functions in sytem.c. It makes sense to me that would be a problem. I assume then that it is more proper to wait until the latest possible moment before popping items from the stack, right?
Note that pike strings can contain NUL chars, so if you pass them directly to a libc function like this it might read a truncated string. Maybe you should check that the passed string doesn't contain NUL?
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Most functions of this type return 0 on failure and nonzero on success, so maybe you should invert the return value.
Or even better would be to declare putenv as returning void and throw an error instead, since the only possible error is ENOMEM, and pike generally throws errors when running out of memory.
Also, wouldn't it be nicer to let the function take the name and the value in separate strings, so that the user doesn't have to glue together one with "="? Then you could also check that the name doesn't contain "=" already.
Actually, I like the idea of throwing an error on failure. If I were able to get this to work properly, i was thinking about modifying the predef::putenv() to call the System.putenv() if it existed.
Bill
/ Brevbäraren
As for "if it existed" I believe it's neigh impossible to find a system where it doesn't.
Windows?
/ David Hedbor
Previous text:
2003-10-17 17:42: Subject: Re: putenv/getenv
Actually, i wrote it from scratch based on looking at other functions in sytem.c.
Indeed there is a function f_get_netinfo_property in system.c that has this error. The others look correct.
/.../ I assume then that it is more proper to wait until the latest possible moment before popping items from the stack, right?
Well, rather to a late enough moment. They can be popped only when you stopped referring to them. If the latest possible moment is before that, you have to restructure your code to solve it.
Tip: The macro stack_pop_n_elems_keep_top should always make it possible to postpone it to just before the return.
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Yes, I think so too.
/.../ i was thinking about modifying the predef::putenv() to call the System.putenv() if it existed.
It'd be necessary to limit leaking according to Marcus' suggestion before you can do that, imo.
As for "if it existed" I believe it's neigh impossible to find a system where it doesn't.
/ Martin Stjernholm, Roxen IS
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-17 17:44: Subject: Re: putenv/getenv
As for "if it existed" I believe it's neigh impossible to find a system where it doesn't.
Windows?
/ David Hedbor
Ah _putenv. Varför i hela friden envisas de med att använda _XXXX hela tiden? Verkar rätt onödigt (i.e skapar inkompatibilitet utan anledning).
/ David Hedbor
Previous text:
2003-10-17 17:47: Subject: Re: putenv/getenv
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
I think it is because putenv is not part of the ISO C standard.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-17 18:04: Subject: Re: putenv/getenv
Ah _putenv. Varför i hela friden envisas de med att använda _XXXX hela tiden? Verkar rätt onödigt (i.e skapar inkompatibilitet utan anledning).
/ David Hedbor
On Fri, 17 Oct 2003, Martin Stjernholm, Roxen IS @ Pike developers forum wrote:
Well, rather to a late enough moment. They can be popped only when you stopped referring to them. If the latest possible moment is before that, you have to restructure your code to solve it.
Tip: The macro stack_pop_n_elems_keep_top should always make it possible to postpone it to just before the return.
That's good to know. I'll keep it in mind. I'll just chalk my errors up to sloppiness due to lack of recent experience :)
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Yes, I think so too.
I've made the suggested changes up to the point of tracking the leaks. Anyone have thoughts about the best way to track them might be?
It'd be necessary to limit leaking according to Marcus' suggestion before you can do that, imo.
Bill
Simply maintain an internal mapping of the settings done through your f_system_putenv, and feed pointers to those strings to putenv(3). The strings will then stay referenced through the mapping, and be freed properly when entries for the same variables are replaced by later calls.
/ Martin Stjernholm, Roxen IS
Previous text:
2003-10-17 18:35: Subject: Re: putenv/getenv
On Fri, 17 Oct 2003, Martin Stjernholm, Roxen IS @ Pike developers forum wrote:
Well, rather to a late enough moment. They can be popped only when you stopped referring to them. If the latest possible moment is before that, you have to restructure your code to solve it.
Tip: The macro stack_pop_n_elems_keep_top should always make it possible to postpone it to just before the return.
That's good to know. I'll keep it in mind. I'll just chalk my errors up to sloppiness due to lack of recent experience :)
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Yes, I think so too.
I've made the suggested changes up to the point of tracking the leaks. Anyone have thoughts about the best way to track them might be?
It'd be necessary to limit leaking according to Marcus' suggestion before you can do that, imo.
Bill
/ Brevbäraren
Micro ITRON is one such system. Just FYI. :-)
I would guess that other embedded systems might also lack that method.
/ Per Hedbor ()
Previous text:
2003-10-17 17:42: Subject: Re: putenv/getenv
Actually, i wrote it from scratch based on looking at other functions in sytem.c.
Indeed there is a function f_get_netinfo_property in system.c that has this error. The others look correct.
/.../ I assume then that it is more proper to wait until the latest possible moment before popping items from the stack, right?
Well, rather to a late enough moment. They can be popped only when you stopped referring to them. If the latest possible moment is before that, you have to restructure your code to solve it.
Tip: The macro stack_pop_n_elems_keep_top should always make it possible to postpone it to just before the return.
what would be the best way to handle strings with NUL? Should they be changed or should an error be thrown? My guess is that an error should be thrown as you really wouldn't want them in the environment, right?
Yes, I think so too.
/.../ i was thinking about modifying the predef::putenv() to call the System.putenv() if it existed.
It'd be necessary to limit leaking according to Marcus' suggestion before you can do that, imo.
As for "if it existed" I believe it's neigh impossible to find a system where it doesn't.
/ Martin Stjernholm, Roxen IS
Theoretically, yes. Perhaps not all that easily, though, there would be some porting work involved (as an example, only the f* file handling routines exists). But it would not be harder do do than the windows port.
Whether or not it would even be desirable or meaningful to try is another question.
It would probably not be.
/ Per Hedbor ()
Previous text:
2003-10-18 10:31: Subject: Re: putenv/getenv
Would those be otherwise able to run pike?
/ Martin Stjernholm, Roxen IS
everything is desirable. meaningfull? what's the meaning of life?
greetings, martin.
pike-devel@lists.lysator.liu.se