diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 0a832ebad13a75..fd0f2a0a55f319 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -201,7 +201,7 @@ struct ForkLaunchInfo { execve(info.argv[0], const_cast(info.argv), info.envp); #if defined(__linux__) - if (errno == ETXTBSY) { + for (int i = 0; i < 50; ++i) { // On android M and earlier we can get this error because the adb daemon // can hold a write handle on the executable even after it has finished // uploading it. This state lasts only a short time and happens only when @@ -210,7 +210,13 @@ struct ForkLaunchInfo { // shell" command in the fork() child before it has had a chance to exec.) // Since this state should clear up quickly, wait a while and then give it // one more go. - usleep(50000); + // If `lldb-server platform` copies the executable in one thread and + // launches gdbserver in another thread (fork+execve), the FD may stay + // opened in the forked child process until execve() even if the first + // thread closed the file. Let's wait a while. + if (errno != ETXTBSY) + break; + usleep(100000); execve(info.argv[0], const_cast(info.argv), info.envp); } #endif diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp b/lldb/source/Host/windows/ProcessLauncherWindows.cpp index baa422c15cae2c..ee5f8fda1d492e 100644 --- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp +++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp @@ -113,14 +113,30 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info, // command line is not empty, its contents may be modified by CreateProcessW. WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0]; - BOOL result = ::CreateProcessW( - wexecutable.c_str(), pwcommandLine, NULL, NULL, TRUE, flags, env_block, - wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), - &startupinfo, &pi); + BOOL result; + DWORD last_error = 0; + // This is the workaround for the error "The process cannot access the file + // because it is being used by another process". Note the executable file is + // installed to the target by the process `lldb-server platform`, but launched + // by the process `lldb-server gdbserver`. Sometimes system may block the file + // for some time after copying. + for (int i = 0; i < 50; ++i) { + result = ::CreateProcessW( + wexecutable.c_str(), pwcommandLine, NULL, NULL, TRUE, flags, env_block, + wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), + &startupinfo, &pi); + if (!result) { + last_error = ::GetLastError(); + if (last_error != ERROR_SHARING_VIOLATION) + break; + ::Sleep(100); + } else + break; + } if (!result) { // Call GetLastError before we make any other system calls. - error.SetError(::GetLastError(), eErrorTypeWin32); + error.SetError(last_error, eErrorTypeWin32); // Note that error 50 ("The request is not supported") will occur if you // try debug a 64-bit inferior from a 32-bit LLDB. }