Allow "make check"-style testing to work with musl C library.

The musl dynamic linker saves a pointer to the process' environment
value of LD_LIBRARY_PATH very early in startup.  When we move/clobber
the environment to make more room for ps status strings, we clobber
that value and thereby prevent libraries from being found via
LD_LIBRARY_PATH, which breaks the use of a temporary installation
for testing purposes.  To fix, stop collecting usable space for
ps status if we notice that the variable we are about to clobber
is LD_LIBRARY_PATH.  This will result in some reduction in how long
the ps status can be, but it's only likely to occur in temporary
test contexts, so it doesn't seem like a big problem.  In any case,
we don't have to do it if we see we are on glibc, which surely is
where the majority of our Linux testing is done.

Thomas Munro, Bruce Momjian, and Tom Lane, per report from Wolfgang
Walther.  Back-patch to all supported branches, with the hope that
we'll set up a buildfarm animal to test on this platform.

Discussion: https://postgr.es/m/fddd1cd6-dc16-40a2-9eb5-d7fef2101488@technowledgy.de
This commit is contained in:
Tom Lane 2024-03-26 11:44:49 -04:00
parent 89e5ef7e21
commit 8a92b70c11
1 changed files with 31 additions and 4 deletions

View File

@ -107,7 +107,8 @@ static char **save_argv;
* (The original argv[] will not be overwritten by this routine, but may be
* overwritten during init_ps_display. Also, the physical location of the
* environment strings may be moved, so this should be called before any code
* that might try to hang onto a getenv() result.)
* that might try to hang onto a getenv() result. But see hack for musl
* within.)
*
* Note that in case of failure this cannot call elog() as that is not
* initialized yet. We rely on write_stderr() instead.
@ -122,7 +123,7 @@ save_ps_display_args(int argc, char **argv)
/*
* If we're going to overwrite the argv area, count the available space.
* Also move the environment to make additional room.
* Also move the environment strings to make additional room.
*/
{
char *end_of_area = NULL;
@ -151,7 +152,33 @@ save_ps_display_args(int argc, char **argv)
for (i = 0; environ[i] != NULL; i++)
{
if (end_of_area + 1 == environ[i])
end_of_area = environ[i] + strlen(environ[i]);
{
/*
* The musl dynamic linker keeps a static pointer to the
* initial value of LD_LIBRARY_PATH, if that is defined in the
* process's environment. Therefore, we must not overwrite the
* value of that setting and thus cannot advance end_of_area
* beyond it. Musl does not define any identifying compiler
* symbol, so we have to do this unless we see a symbol
* identifying a Linux libc we know is safe.
*/
#if defined(__linux__) && (!defined(__GLIBC__) && !defined(__UCLIBC__))
if (strncmp(environ[i], "LD_LIBRARY_PATH=", 16) == 0)
{
/*
* We can overwrite the name, but stop at the equals sign.
* Future loop iterations will not find any more
* contiguous space, but we don't break early because we
* need to count the total number of environ[] entries.
*/
end_of_area = environ[i] + 15;
}
else
#endif
{
end_of_area = environ[i] + strlen(environ[i]);
}
}
}
ps_buffer = argv[0];
@ -183,7 +210,7 @@ save_ps_display_args(int argc, char **argv)
* If we're going to change the original argv[] then make a copy for
* argument parsing purposes.
*
* (NB: do NOT think to remove the copying of argv[], even though
* NB: do NOT think to remove the copying of argv[], even though
* postmaster.c finishes looking at argv[] long before we ever consider
* changing the ps display. On some platforms, getopt() keeps pointers
* into the argv array, and will get horribly confused when it is