Dear maintainer,
With glibc >= 2.44, <spawn.h> declares posix_spawn_file_actions_addchdir
as an asm redirection alias (__REDIRECT_NTH) to
posix_spawn_file_actions_addchdir_np according to POSIX.1-2024.
gnulib sets REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=1, compiling
spawn_faction_addchdir.c which returns posix_spawn_file_actions_addchdir_np.
Because asm redirection cannot be undone by #undef, gcc emits the function
definition as posix_spawn_file_actions_addchdir_np, calling itself in an
infinite recursion.
On i386, this causes an immediate SIGSEGV (exit code 139) during gnulib
tests. On amd64 and arm64, it hangs test-execute.sh and
test-posix_spawn-chdir, leading to FTBFS on Ubuntu stonking (LP: #2167365).
In glibc >= 2.44, posix_spawn_file_actions_addchdir is already provided
natively by libc. Guarding spawn_faction_addchdir.c when defined __GLIBC__
&& defined __USE_XOPEN2K24XSI prevents the recursive definition and allows
clean compilation and test suite execution.
Attached is the patch addressing this issue.
Thanks,
Viktor Pashaiev <w.paszajew@gmail.com>
--- a/gettext-tools/gnulib-lib/spawn_faction_addchdir.c
+++ b/gettext-tools/gnulib-lib/spawn_faction_addchdir.c
@@ -28,43 +28,58 @@
/* Add an action to FILE-ACTIONS which tells the implementation to call
'chdir' to the given directory during the 'spawn' call. */
+#if !REPLACE_POSIX_SPAWN
+
+# if defined __GLIBC__ && defined __USE_XOPEN2K24XSI
+/* In glibc >= 2.44, <spawn.h> already defines posix_spawn_file_actions_addchdir
+ as an alias to posix_spawn_file_actions_addchdir_np. Defining it here would
+ create a recursive call to itself and shadow libc.so.6. */
+typedef int gl_posix_spawn_file_actions_addchdir_unused_t;
+# else
int
posix_spawn_file_actions_addchdir (posix_spawn_file_actions_t *file_actions,
const char *path)
-#undef posix_spawn_file_actions_addchdir
+# undef posix_spawn_file_actions_addchdir
{
-#if !REPLACE_POSIX_SPAWN
return posix_spawn_file_actions_addchdir_np (file_actions, path);
-#else
- {
- /* Copy PATH, because the caller may free it before calling posix_spawn()
- or posix_spawnp(). */
- char *path_copy = strdup (path);
- if (path_copy == NULL)
- return ENOMEM;
+}
+# endif
+
+#else
+
+int
+posix_spawn_file_actions_addchdir (posix_spawn_file_actions_t *file_actions,
+ const char *path)
+# undef posix_spawn_file_actions_addchdir
+{
+ /* Copy PATH, because the caller may free it before calling posix_spawn()
+ or posix_spawnp(). */
+ char *path_copy = strdup (path);
+ if (path_copy == NULL)
+ return ENOMEM;
+
+ /* Allocate more memory if needed. */
+ if (file_actions->_used == file_actions->_allocated
+ && __posix_spawn_file_actions_realloc (file_actions) != 0)
+ {
+ /* This can only mean we ran out of memory. */
+ free (path_copy);
+ return ENOMEM;
+ }
+
+ {
+ struct __spawn_action *rec;
+
+ /* Add the new value. */
+ rec = &file_actions->_actions[file_actions->_used];
+ rec->tag = spawn_do_chdir;
+ rec->action.chdir_action.path = path_copy;
+
+ /* Account for the new entry. */
+ ++file_actions->_used;
+
+ return 0;
+ }
}
+
+#endif