git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 1/5] wrapper.c: add x{un,}setenv(), and use xsetenv() in environment.c

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Sep 20, 2021, 23:17 UTC
Message-ID
<87y27qakzx.fsf@evledraar.gmail.com>
In-Reply-To
<YUkC7RIDR7pQWsPh@nand.local>
On Mon, Sep 20 2021, Taylor Blau wrote:
Show 38 quoted lines
> On Sun, Sep 19, 2021 at 10:47:15AM +0200, Ævar Arnfjörð Bjarmason wrote:
>> Add fatal wrappers for setenv() and unsetenv(). In d7ac12b25d3 (Add
>> set_git_dir() function, 2007-08-01) we started checking its return
>> value, and since 48988c4d0c3 (set_git_dir: die when setenv() fails,
>> 2018-03-30) we've had set_git_dir_1() die if we couldn't set it.
>>
>> Let's provide a wrapper for both, this will be useful in many other
>> places, a subsequent patch will make another use of xsetenv().
>
> Makes sense.
>
>> We could make these return "void" (as far as I can tell there's no
>> other x*() wrappers that needed to make that decision before),
>> i.e. our "return 0" is only to indicate that we didn't error, which we
>> would have died on. Let's return "int" instead to be consistent with
>> the C library function signatures, including for any future code that
>> expects a pointer to a setenv()-like function.
>
> This may be a little over-clever ;). It is cute, but returning an int
> makes xsetenv a drop-in replacement for setenv. Which is nice, but it
> makes it all too-easy to take code like:
>
>   if (setenv(...) < 0)
>     die(_("..."));
>
> and replace it with
>
>   if (xsetenv(...) < 0)
>
> which makes the whole conditional redundant, since the wrappers are
> guaranteed not to return an error.
>
> In other words, I like the idea that s/setenv/x&/ causes a compile-time
> error, and returning an int from these wrappers prevents that from
> happening.
>
> This may be a little too-theoretical, and you're certainly free to
> disagree, just my $0.02.

I'm fine with doing that in principle, I couldn't find any "x*()" wrappers with different signatures. Yes, having the compiler complain because you used a "void" return value would be nice.

I did have some vague notion that this might interact badly with something in compat, i.e. if setenv() or unsetenv() was a fallback, but I can't think now of why that wouldn't work...

Show 14 quoted lines
>> I think it would be OK skip the NULL check of the "name" here for the
>> calls to die_errno(). Almost all of our setenv() callers are taking a
>> constant string hardcoded in the source as the first argument, and for
>> the rest we can probably assume they've done the NULL check
>> themselves. Even if they didn't, modern C libraries are forgiving
>> about it (e.g. glibc formatting it as "(null)"), on those that aren't,
>> well, we were about to die anyway. But let's include the check anyway
>> for good measure.
>
> This I think is a good call. I agree in practice that most times we'd be
> just fine to pass null to printf() (as we have seen from 88617d11f9
> (multi-pack-index: fix potential segfault without sub-command,
> 2021-07-19) ;)). But there's no reason to rely on risky assumptions when
> it's easy to avoid doing so.
*nod*
Show 26 quoted lines
>> diff --git a/wrapper.c b/wrapper.c
>> index 7c6586af321..95f989260cd 100644
>> --- a/wrapper.c
>> +++ b/wrapper.c
>> @@ -145,6 +145,21 @@ void *xcalloc(size_t nmemb, size_t size)
>>  	return ret;
>>  }
>>
>> +int xsetenv(const char *name, const char *value, int overwrite)
>> +{
>> +	if (setenv(name, value, overwrite))
>> +		die_errno("setenv(%s, '%s', %d) failed", name ? name : "(null)",
>> +			  value, overwrite);
>> +	return 0;
>> +}
>> +
>> +int xunsetenv(const char *name)
>> +{
>> +	if (!unsetenv(name))
>> +		die_errno("unsetenv(%s) failed", name ? name : "(null)");
>> +	return 0;
>> +}
>> +
>
> For what it's worth, I find these new messages a little wordy. Maybe
> we should just sticky "could not (un)set %s"?
Sure, will change it.

I think I may have wanted to include the "overwrite" in the setenv() in some way though, so you'd know if it failed because the libc call "really" failed, v.s. we just had an existing value in the environment and didn't set "overwrite".

But reading the docs again that won't work, since it'll succeed if it can't write that key, i.e. the caller with overwrite=0 needs to follow-up with a getenv() to see if their value or someone else's was set (or more probably, they don't care, which is why they used overwrite=0).

So it doesn't matter either way for xsetenv(), will make it less chatty.
Previous: Taylor BlauNext: Ævar Arnfjörð Bjarmason
Message 17 of 34 in “repo-settings.c: refactor for clarity, get rid of hacks etc.”
  1. 0/5 repo-settings.c: refactor for clarity, get rid of hacks etc.Ævar Arnfjörð Bjarmason, Sep 16, 2021
  2. 1/5 wrapper.c: add x{un,}setenv(), and use xsetenv() in environment.cÆvar Arnfjörð Bjarmason, Sep 16, 2021
  3. Junio C HamanoSep 17, 2021
  4. Ævar Arnfjörð BjarmasonSep 17, 2021
  5. 2/5 environment.c: remove test-specific "ignore_untracked..." variableÆvar Arnfjörð Bjarmason, Sep 16, 2021
  6. Junio C HamanoSep 17, 2021
  7. 3/5 read-cache & fetch-negotiator: check "enum" values in switch()Ævar Arnfjörð Bjarmason, Sep 16, 2021
  8. Junio C HamanoSep 17, 2021
  9. 5/5 repository.h: don't use a mix of int and bitfieldsÆvar Arnfjörð Bjarmason, Sep 16, 2021
  10. 4/5 repo-settings.c: simplify the setupÆvar Arnfjörð Bjarmason, Sep 16, 2021
  11. 0/5 repo-settings.c: refactor for clarity, get rid of hacks etc.Ævar Arnfjörð Bjarmason, Sep 19, 2021
  12. 2/5 environment.c: remove test-specific "ignore_untracked..." variableÆvar Arnfjörð Bjarmason, Sep 19, 2021
  13. Taylor BlauSep 20, 2021
  14. Ævar Arnfjörð BjarmasonSep 20, 2021
  15. 1/5 wrapper.c: add x{un,}setenv(), and use xsetenv() in environment.cÆvar Arnfjörð Bjarmason, Sep 19, 2021
  16. Taylor BlauSep 20, 2021
  17. Ævar Arnfjörð BjarmasonSep 20, 2021
  18. 3/5 read-cache & fetch-negotiator: check "enum" values in switch()Ævar Arnfjörð Bjarmason, Sep 19, 2021
  19. Taylor BlauSep 20, 2021
  20. Ævar Arnfjörð BjarmasonSep 20, 2021
  21. 5/5 repository.h: don't use a mix of int and bitfieldsÆvar Arnfjörð Bjarmason, Sep 19, 2021
  22. Taylor BlauSep 20, 2021
  23. 4/5 repo-settings.c: simplify the setupÆvar Arnfjörð Bjarmason, Sep 19, 2021
  24. Derrick StoleeSep 20, 2021
  25. Taylor BlauSep 20, 2021
  26. 0/5 repo-settings.c: refactor for clarity, get rid of hacks etc.Ævar Arnfjörð Bjarmason, Sep 21, 2021
  27. 1/5 wrapper.c: add x{un,}setenv(), and use xsetenv() in environment.cÆvar Arnfjörð Bjarmason, Sep 21, 2021
  28. 2/5 environment.c: remove test-specific "ignore_untracked..." variableÆvar Arnfjörð Bjarmason, Sep 21, 2021
  29. 3/5 read-cache & fetch-negotiator: check "enum" values in switch()Ævar Arnfjörð Bjarmason, Sep 21, 2021
  30. 4/5 repo-settings.c: simplify the setupÆvar Arnfjörð Bjarmason, Sep 21, 2021
  31. 5/5 repository.h: don't use a mix of int and bitfieldsÆvar Arnfjörð Bjarmason, Sep 21, 2021
  32. Derrick StoleeSep 21, 2021
  33. Taylor BlauSep 21, 2021
  34. Junio C HamanoSep 22, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.