Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py @@ -85,7 +85,34 @@ # not working? @not_remote_testsuite_ready @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20265") - def test_set_working_dir(self): + def test_set_working_dir_nonexisting(self): + """Test that '-w dir' fails to set the working dir when running the inferior with a dir which doesn't exist.""" + d = {'CXX_SOURCES': 'print_cwd.cpp'} + self.build(dictionary=d) + self.setTearDownCleanup(d) + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe) + + mywd = 'my_working_dir' + out_file_name = "my_working_dir_test.out" + err_file_name = "my_working_dir_test.err" + + my_working_dir_path = self.getBuildArtifact(mywd) + out_file_path = os.path.join(my_working_dir_path, out_file_name) + err_file_path = os.path.join(my_working_dir_path, err_file_name) + + # Check that we get an error when we have a nonexisting path + invalid_dir_path = mywd + 'z' + launch_command = "process launch -w %s -o %s -e %s" % ( + invalid_dir_path, out_file_path, err_file_path) + + self.expect( + launch_command, error=True, patterns=[ + "error:.* No such file or directory: %s" % + invalid_dir_path]) + + @not_remote_testsuite_ready + def test_set_working_dir_existing(self): """Test that '-w dir' sets the working dir when running the inferior.""" d = {'CXX_SOURCES': 'print_cwd.cpp'} self.build(dictionary=d) @@ -109,16 +136,6 @@ except OSError: pass - # Check that we get an error when we have a nonexisting path - launch_command = "process launch -w %s -o %s -e %s" % ( - my_working_dir_path + 'z', out_file_path, err_file_path) - - self.expect( - launch_command, error=True, patterns=[ - "error:.* No such file or directory: %sz" % - my_working_dir_path]) - - # Really launch the process launch_command = "process launch -w %s -o %s -e %s" % ( my_working_dir_path, out_file_path, err_file_path) Index: lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py +++ lldb/trunk/packages/Python/lldbsuite/test/lldbtest.py @@ -1833,7 +1833,7 @@ # Maximum allowed attempts when launching the inferior process. # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. - maxLaunchCount = 3 + maxLaunchCount = 1 # Time to wait before the next launching attempt in second(s). # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. Index: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp =================================================================== --- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp +++ lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp @@ -96,6 +96,12 @@ wexecutable.c_str(), &wcommandLine[0], NULL, NULL, TRUE, flags, env_block, wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(), &startupinfo, &pi); + + if (!result) { + // Call GetLastError before we make any other system calls. + error.SetError(::GetLastError(), eErrorTypeWin32); + } + if (result) { // Do not call CloseHandle on pi.hProcess, since we want to pass that back // through the HostProcess. @@ -110,7 +116,8 @@ ::CloseHandle(stderr_handle); if (!result) - error.SetError(::GetLastError(), eErrorTypeWin32); + return HostProcess(); + return HostProcess(pi.hProcess); } Index: lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ lldb/trunk/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -181,13 +181,19 @@ lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); if (terminate) { - // Initiate the termination before continuing the exception, so that the - // next debug event we get is the exit process event, and not some other - // event. - BOOL terminate_suceeded = TerminateProcess(handle, 0); - LLDB_LOG(log, - "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", - handle, pid, terminate_suceeded); + if (handle != nullptr && handle != LLDB_INVALID_PROCESS) { + // Initiate the termination before continuing the exception, so that the + // next debug event we get is the exit process event, and not some other + // event. + BOOL terminate_suceeded = TerminateProcess(handle, 0); + LLDB_LOG(log, + "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", + handle, pid, terminate_suceeded); + } else { + LLDB_LOG(log, + "NOT calling TerminateProcess because the inferior is not valid ({0}, 0) (inferior={1})", + handle, pid); + } } // If we're stuck waiting for an exception to continue (e.g. the user is at a Index: lldb/trunk/source/Plugins/Process/Windows/Common/ProcessWindows.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ lldb/trunk/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -234,6 +234,16 @@ Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); Status result; + + FileSpec working_dir = launch_info.GetWorkingDirectory(); + namespace fs = llvm::sys::fs; + if (working_dir && (!working_dir.ResolvePath() || + !fs::is_directory(working_dir.GetPath()))) { + result.SetErrorStringWithFormat("No such file or directory: %s", + working_dir.GetCString()); + return result; + } + if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { StreamString stream; stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can "