[PATCH v2 0/3] MR10926: ntdll,msv1_0: Add fallback paths for systems without posix_spawn().
This adds fallback implementations for posix_spawn() usage in ntdll and msv1_0. Older Android versions do not provide posix_spawn() or posix_spawnp(). The affected code paths only need simple helper process startup and only distinguish success from failure, so this keeps the existing posix_spawn() implementation where available and uses vfork() with execv()/execvp() otherwise. The ntdll loader path preserves the existing execv-style behavior for a fully built path. The msv1_0 ntlm_auth path preserves the posix_spawnp-style PATH lookup by using execvp() in the fallback. -- v2: msv1_0: Add a fallback for ntlm_auth startup without posix_spawn ntdll: Add a fallback for helper startup without posix_spawn configure: Check for posix_spawn https://gitlab.winehq.org/wine/wine/-/merge_requests/10926
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- configure | 6 ++++++ configure.ac | 1 + include/config.h.in | 3 +++ 3 files changed, 10 insertions(+) diff --git a/configure b/configure index fda5e60e415..118009ca227 100755 --- a/configure +++ b/configure @@ -21980,6 +21980,12 @@ if test "x$ac_cv_func_posix_fallocate" = xyes then : printf "%s\n" "#define HAVE_POSIX_FALLOCATE 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn" +if test "x$ac_cv_func_posix_spawn" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" if test "x$ac_cv_func_prctl" = xyes diff --git a/configure.ac b/configure.ac index 485a1370b06..3cfb61a1adb 100644 --- a/configure.ac +++ b/configure.ac @@ -2119,6 +2119,7 @@ AC_CHECK_FUNCS(\ port_create \ posix_fadvise \ posix_fallocate \ + posix_spawn \ prctl \ process_vm_readv \ process_vm_writev \ diff --git a/include/config.h.in b/include/config.h.in index 551771eaa6a..82d08d53b5f 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -336,6 +336,9 @@ /* Define to 1 if you have the 'posix_fallocate' function. */ #undef HAVE_POSIX_FALLOCATE +/* Define to 1 if you have the 'posix_spawn' function. */ +#undef HAVE_POSIX_SPAWN + /* Define to 1 if you have the 'prctl' function. */ #undef HAVE_PRCTL -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10926
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/ntdll/unix/loader.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index c1e6b588dcb..491cdfce586 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -30,7 +30,6 @@ #include <stdarg.h> #include <stdio.h> #include <signal.h> -#include <spawn.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> @@ -39,6 +38,9 @@ #include <sys/wait.h> #include <unistd.h> #include <dlfcn.h> +#ifdef HAVE_POSIX_SPAWN +#include <spawn.h> +#endif #ifdef HAVE_PWD_H # include <pwd.h> #endif @@ -249,10 +251,27 @@ static char *build_relative_path( const char *base, const char *from, const char /* build a path to a binary and exec it */ static int build_path_and_exec( pid_t *pid, const char *dir, const char *name, char **argv ) { - int ret; + int ret = 0; argv[0] = build_path( dir, name ); +#ifdef HAVE_POSIX_SPAWN ret = posix_spawn( pid, argv[0], NULL, NULL, argv, environ ); +#else + { + volatile int failed = 0; + pid_t child = vfork(); + + if (!child) + { + execv( argv[0], argv ); + failed = 1; + _exit(127); + } + + ret = child == -1 || failed ? 127 : 0; + if (!ret) *pid = child; + } +#endif free( argv[0] ); return ret; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10926
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/msv1_0/unixlib.c | 51 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/dlls/msv1_0/unixlib.c b/dlls/msv1_0/unixlib.c index e9c2088da9e..880a4aeb8bd 100644 --- a/dlls/msv1_0/unixlib.c +++ b/dlls/msv1_0/unixlib.c @@ -28,7 +28,6 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> -#include <spawn.h> #include <sys/wait.h> #include "ntstatus.h" #include "windef.h" @@ -36,6 +35,10 @@ #include "winbase.h" #include "sspi.h" +#ifdef HAVE_POSIX_SPAWN +#include <spawn.h> +#endif + #include "wine/debug.h" #include "unixlib.h" @@ -161,9 +164,12 @@ static NTSTATUS ntlm_fork( void *args ) { const struct fork_params *params = args; struct ntlm_ctx *ctx = params->ctx; - posix_spawn_file_actions_t file_actions; - int pipe_in[2], pipe_out[2], err; + int pipe_in[2], pipe_out[2]; NTSTATUS status = STATUS_SUCCESS; +#ifdef HAVE_POSIX_SPAWN + int err; + posix_spawn_file_actions_t file_actions; +#endif #ifdef HAVE_PIPE2 if (pipe2( pipe_in, O_CLOEXEC ) < 0) @@ -187,6 +193,7 @@ static NTSTATUS ntlm_fork( void *args ) fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC ); } +#ifdef HAVE_POSIX_SPAWN posix_spawn_file_actions_init( &file_actions ); posix_spawn_file_actions_adddup2( &file_actions, pipe_out[0], 0 ); @@ -207,13 +214,47 @@ static NTSTATUS ntlm_fork( void *args ) status = STATUS_UNSUCCESSFUL; } + posix_spawn_file_actions_destroy( &file_actions ); +#else + { + volatile int failed = 0; + pid_t child = vfork(); + + if (!child) + { + if (dup2( pipe_out[0], 0 ) == -1 || dup2( pipe_in[1], 1 ) == -1) + { + failed = 1; + _exit(127); + } + + close( pipe_out[0] ); + close( pipe_out[1] ); + close( pipe_in[0] ); + close( pipe_in[1] ); + + execvp( params->argv[0], params->argv ); + failed = 1; + _exit(127); + } + + if (child == -1 || failed) + { + ctx->pid = -1; + write( pipe_in[1], "BH\n", 3 ); + ERR_(winediag)( "Can't start ntlm_auth. " + "Usually you can find it in the winbind package of your distribution.\n" ); + status = STATUS_UNSUCCESSFUL; + } + else ctx->pid = child; + } +#endif + ctx->pipe_in = pipe_in[0]; close( pipe_in[1] ); ctx->pipe_out = pipe_out[1]; close( pipe_out[0] ); - posix_spawn_file_actions_destroy( &file_actions ); - return status; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10926
On Mon May 18 05:01:22 2026 +0000, Hans Leidekker wrote:
ntlm_auth is unlikely to be available on Android and NTLM is used sporadically so I'm inclined to disable it and see if any demand turns up. You should split the commit: one per dll. I don't think waiting until demand turns up will work well in this case.
Wine Android is not really used at the moment because the target is not in a practically usable state yet. There are not even proper build scripts for it right now, and this work is part of trying to revive it. The downstream Android-based projects that use Wine already carry their own workaround, usually by providing a ported posix_spawn() implementation, so this is unlikely to show up naturally as upstream user demand. Disabling ntlm_auth on Android would mostly mask this particular failure instead of fixing the underlying portability issue. ntlm_auth is only one of the helper startup paths that currently assumes posix_spawn(); the same assumption exists elsewhere too. I have also split the changes into separate commits as requested. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140305
On Mon May 18 05:01:22 2026 +0000, Twaik Yont wrote:
I don't think waiting until demand turns up will work well in this case. Wine Android is not really used at the moment because the target is not in a practically usable state yet. There are not even proper build scripts for it right now, and this work is part of trying to revive it. The downstream Android-based projects that use Wine already carry their own workaround, usually by providing a ported posix_spawn() implementation, so this is unlikely to show up naturally as upstream user demand. Disabling ntlm_auth on Android would mostly mask this particular failure instead of fixing the underlying portability issue. ntlm_auth is only one of the helper startup paths that currently assumes posix_spawn(); the same assumption exists elsewhere too. I have also split the changes into separate commits as requested. Do those downstream projects ship ntlm_auth?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140306
On Mon May 18 06:24:30 2026 +0000, Hans Leidekker wrote:
Do those downstream projects ship ntlm_auth? I did not see any patches which disable it.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140310
On Mon May 18 06:29:43 2026 +0000, Twaik Yont wrote:
I did not see any patches which disable it. ntlm_auth is not part of Wine. It's a tool from the Samba project.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140323
On Mon May 18 07:12:06 2026 +0000, Hans Leidekker wrote:
ntlm_auth is not part of Wine. It's a tool from the Samba project. Right, ntlm_auth is external to Wine.
However, this patch is not trying to special-case Android or decide whether ntlm_auth should be supported there. It only adds a fallback for systems where posix_spawn() is not available. Even if Android is currently the only such target in practice, disabling ntlm_auth there would be a separate change and could accidentally break setups that provide a Samba ntlm_auth-compatible helper. It would also mask the posix_spawn() portability issue rather than fixing it. I'd prefer to keep the existing ntlm_auth behavior unchanged and only make the helper startup path work without posix_spawn(). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140328
On Mon May 18 07:51:10 2026 +0000, Twaik Yont wrote:
Right, ntlm_auth is external to Wine. However, this patch is not trying to special-case Android or decide whether ntlm_auth should be supported there. It only adds a fallback for systems where posix_spawn() is not available. Even if Android is currently the only such target in practice, disabling ntlm_auth there would be a separate change and could accidentally break setups that provide a Samba ntlm_auth-compatible helper. It would also mask the posix_spawn() portability issue rather than fixing it. I'd prefer to keep the existing ntlm_auth behavior unchanged and only make the helper startup path work without posix_spawn(). In the case of ntlm_auth I don't think the extra complexity is worth the trouble.
TBH I'm not convinced that even in ntdll we have to go out of our way to support old Android versions. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140330
On Mon May 18 07:57:50 2026 +0000, Alexandre Julliard wrote:
In the case of ntlm_auth I don't think the extra complexity is worth the trouble. TBH I'm not convinced that even in ntdll we have to go out of our way to support old Android versions. The current minimum target is Android 8, and I would prefer not to raise it to Android 9 just because of posix_spawn().
posix_spawn() is only available starting with Android 9, so using it unconditionally would leave Android 8 devices behind. I already had users complain that some older devices, for example ZenPad-class devices, are no longer covered after my recent changes, and I would rather avoid adding another group of affected users if the workaround is reasonably small. I agree that ntlm_auth itself is probably not important enough on Android to justify much complexity, so I can drop the msv1_0 part if needed. My main concern is ntdll, because without a fallback there Android 8 becomes unsupported in practice unless we explicitly raise the minimum version to Android 9. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140337
On Mon May 18 08:44:35 2026 +0000, Twaik Yont wrote:
The current minimum target is Android 8, and I would prefer not to raise it to Android 9 just because of posix_spawn(). posix_spawn() is only available starting with Android 9, so using it unconditionally would leave Android 8 devices behind. I already had users complain that some older devices, for example ZenPad-class devices, are no longer covered after my recent changes, and I would rather avoid adding another group of affected users if the workaround is reasonably small. I agree that ntlm_auth itself is probably not important enough on Android to justify much complexity, so I can drop the msv1_0 part if needed. My main concern is ntdll, because without a fallback there Android 8 becomes unsupported in practice unless we explicitly raise the minimum version to Android 9. I can change the msv1_0 part so that ntlm_fork explicitly returns STATUS_NOT_IMPLEMENTED on systems where posix_spawn() is unavailable, in order to avoid the extra complexity there.
But I would strongly prefer not to raise the minimum Android version to 9 just because of posix_spawn(). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_140520
Closing in favor of !11096. It's a shame we have to drop support for older Android versions, but reimplementing process spawning without posix_spawn() is not considered worth the added complexity. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926#note_142512
This merge request was closed by Twaik Yont. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10926
participants (4)
-
Alexandre Julliard (@julliard) -
Hans Leidekker (@hans) -
Twaik Yont -
Twaik Yont (@twaik)