Sometimes, when the wineprefix is broken, trying to switch to the 64-bit wineboot starts the 32-bit executable instead, resulting in a slow-burn fork bomb. Fortunately this is rare but typically results in a session crash and the loss of unsaved unrelated documents. So detect and nip infinite restart loops in the bud.
Signed-off-by: Francois Gouget fgouget@codeweavers.com --- The troublesome code has been present for the past 10 years so this issue is pretty rare. So an alternative would be to just ignore it. But because of the potential for data loss in unrelated applications I'd still feel better if this fork-bomb had a safety pin. --- programs/wineboot/wineboot.c | 42 +++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index 9427448b612..9d87c26c207 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -1616,27 +1616,39 @@ int __cdecl main( int argc, char *argv[] )
if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64) { - STARTUPINFOW si; - PROCESS_INFORMATION pi; WCHAR filename[MAX_PATH]; - void *redir; - DWORD exit_code;
- memset( &si, 0, sizeof(si) ); - si.cb = sizeof(si); GetModuleFileNameW( 0, filename, MAX_PATH ); - - Wow64DisableWow64FsRedirection( &redir ); - if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )) + if (GetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", NULL, 0) + && GetLastError() != ERROR_ENVVAR_NOT_FOUND) + { + WINE_ERR( "got an infinite loop while starting the 64-bit %s\n", wine_dbgstr_w(filename) ); + } + else { - WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) ); - WaitForSingleObject( pi.hProcess, INFINITE ); - GetExitCodeProcess( pi.hProcess, &exit_code ); - ExitProcess( exit_code ); + STARTUPINFOW si; + PROCESS_INFORMATION pi; + void *redir; + DWORD exit_code; + + Wow64DisableWow64FsRedirection( &redir ); + SetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", "1"); + + memset( &si, 0, sizeof(si) ); + si.cb = sizeof(si); + if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )) + { + WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) ); + WaitForSingleObject( pi.hProcess, INFINITE ); + GetExitCodeProcess( pi.hProcess, &exit_code ); + ExitProcess( exit_code ); + } + else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() ); + + Wow64RevertWow64FsRedirection( redir ); } - else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() ); - Wow64RevertWow64FsRedirection( redir ); } + SetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", NULL);
for (i = 1; i < argc; i++) {