On Linux, when an exec happens and there are thread plans alive, a crash occurs because the base thread plan invokes GetPrivateStopInfo, which ends up invoking GetThread().GetPrivateStopInfo(), and as the thread is already dead, that call crashes.
The method ProcessGDBRemote::SetLastStopPacket is the one who clears the threads upon an exec and before the base thread plan resumes its work.
This doesn't happen on Darwin though. For some context, on Linux, after a process performs exec, the thread id doesn't change. On Darwin it does change, which helps LLDB clear the thread automatically.
A simple fix is to clear all thread plans in the place where threads are already being cleared.
For some final context, the existing test was not failing because there were no thread plans active before getting to the exec.